* HttpListener2Test.cs: Added test for bug #513849.
[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] // bug #471782
101                 public void CloseRequestStreamAfterReadingResponse ()
102                 {
103                         IPEndPoint ep = new IPEndPoint (IPAddress.Loopback, 8000);
104                         string url = "http://" + IPAddress.Loopback.ToString () + ":8000/test/";
105
106                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (EchoRequestHandler))) {
107                                 responder.Start ();
108
109                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
110                                 req.Method = "POST";
111                                 req.Timeout = 2000;
112                                 req.ReadWriteTimeout = 2000;
113
114                                 byte [] data = new byte [128];
115                                 req.ContentLength = data.Length;
116
117                                 Stream rs = req.GetRequestStream ();
118                                 rs.Write (data, 0, data.Length);
119                                 rs.Flush ();
120
121                                 HttpWebResponse response = (HttpWebResponse) req.GetResponse ();
122                                 response.Close ();
123
124                                 rs.Close ();
125
126                                 responder.Stop ();
127                         }
128                 }
129
130                 [Test]
131                 [Category("InetAccess")]
132                 public void Cookies1 ()
133                 {
134                         // The purpose of this test is to ensure that the cookies we get from a request
135                         // are stored in both, the CookieCollection in HttpWebResponse and the CookieContainer
136                         // in HttpWebRequest.
137                         // If this URL stops sending *one* and only one cookie, replace it.
138                         string url = "http://www.elmundo.es";
139                         CookieContainer cookies = new CookieContainer ();
140                         HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
141                         req.KeepAlive = false;
142                         req.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv; 1.7.6) Gecko/20050317 Firefox/1.0.2";
143                         req.CookieContainer = cookies;
144                         Assertion.AssertEquals ("#01", 0, cookies.Count);
145                         using (HttpWebResponse res = (HttpWebResponse) req.GetResponse()) {
146                                 CookieCollection coll = req.CookieContainer.GetCookies (new Uri (url));
147                                 Assertion.AssertEquals ("#02", 1, coll.Count);
148                                 Assertion.AssertEquals ("#03", 1, res.Cookies.Count);
149                                 Cookie one = coll [0];
150                                 Cookie two = res.Cookies [0];
151                                 Assertion.AssertEquals ("#04", true, object.ReferenceEquals (one, two));
152                         }
153                 }
154
155 #if !TARGET_JVM //NotWorking
156                 [Test]
157                 public void SslClientBlock ()
158                 {
159                         // This tests that the write request/initread/write body sequence does not hang
160                         // when using SSL.
161                         // If there's a regression for this, the test will hang.
162                         ServicePointManager.CertificatePolicy = new AcceptAllPolicy ();
163                         try {
164                                 SslHttpServer server = new SslHttpServer ();
165                                 server.Start ();
166
167                                 string url = String.Format ("https://{0}:{1}/nothing.html", server.IPAddress, server.Port);
168                                 HttpWebRequest request = (HttpWebRequest) WebRequest.Create (url);
169                                 request.Method = "POST";
170                                 Stream stream = request.GetRequestStream ();
171                                 byte [] bytes = new byte [100];
172                                 stream.Write (bytes, 0, bytes.Length);
173                                 stream.Close ();
174                                 HttpWebResponse resp = (HttpWebResponse) request.GetResponse ();
175                                 Assertion.AssertEquals ("StatusCode", 200, (int) resp.StatusCode);
176                                 StreamReader sr = new StreamReader (resp.GetResponseStream (), Encoding.UTF8);
177                                 string x = sr.ReadToEnd ();
178                                 sr.Close ();
179                                 resp.Close ();
180                                 server.Stop ();
181                                 if (server.Error != null)
182                                         throw server.Error;
183                         } finally {
184                                 ServicePointManager.CertificatePolicy = null;
185                         }
186                 }
187 #endif
188                 [Test]
189 #if TARGET_JVM
190                 [Category("NotWorking")]
191 #endif
192                 public void Missing_ContentEncoding ()
193                 {
194                         ServicePointManager.CertificatePolicy = new AcceptAllPolicy ();
195                         try {
196                                 BadChunkedServer server = new BadChunkedServer ();
197                                 server.Start ();
198
199                                 string url = String.Format ("http://{0}:{1}/nothing.html", server.IPAddress, server.Port);
200                                 HttpWebRequest request = (HttpWebRequest) WebRequest.Create (url);
201                                 request.Method = "GET";
202                                 HttpWebResponse resp = (HttpWebResponse) request.GetResponse ();
203                                 Assert.AreEqual ("", resp.ContentEncoding);
204                                 resp.Close ();
205                                 server.Stop ();
206                                 if (server.Error != null)
207                                         throw server.Error;
208                         } finally {
209                                 ServicePointManager.CertificatePolicy = null;
210                         }
211                 }
212
213                 [Test]
214 #if TARGET_JVM
215                 [Category ("NotWorking")]
216 #endif
217                 public void BadServer_ChunkedClose ()
218                 {
219                         // The server will send a chunked response without a 'last-chunked' mark
220                         // and then shutdown the socket for sending.
221                         BadChunkedServer server = new BadChunkedServer ();
222                         server.Start ();
223                         string url = String.Format ("http://{0}:{1}/nothing.html", server.IPAddress, server.Port);
224                         HttpWebRequest request = (HttpWebRequest) WebRequest.Create (url);
225                         HttpWebResponse resp = (HttpWebResponse) request.GetResponse ();
226                         string x = null;
227                         try {
228                                 byte [] bytes = new byte [32];
229                                 // Using StreamReader+UTF8Encoding here fails on MS runtime
230                                 Stream stream = resp.GetResponseStream ();
231                                 int nread = stream.Read (bytes, 0, 32);
232                                 Assertion.AssertEquals ("#01", 16, nread);
233                                 x = Encoding.ASCII.GetString (bytes, 0, 16);
234                         } finally {
235                                 resp.Close ();
236                                 server.Stop ();
237                         }
238
239                         if (server.Error != null)
240                                 throw server.Error;
241
242                         Assertion.AssertEquals ("1234567890123456", x);
243                 }
244
245                 [Test]
246                 [Ignore ("This test asserts that our code violates RFC 2616")]
247                 public void MethodCase ()
248                 {
249                         ListDictionary methods = new ListDictionary ();
250 #if NET_2_0
251                         methods.Add ("post", "POST");
252                         methods.Add ("puT", "PUT");
253 #else
254                         methods.Add ("post", "post");
255                         methods.Add ("puT", "puT");
256 #endif
257                         methods.Add ("POST", "POST");
258                         methods.Add ("whatever", "whatever");
259                         methods.Add ("PUT", "PUT");
260
261                         IPEndPoint ep = new IPEndPoint (IPAddress.Loopback, 8000);
262                         string url = "http://" + IPAddress.Loopback.ToString () + ":8000/test/";
263
264                         foreach (DictionaryEntry de in methods) {
265                                 SocketResponder responder = new SocketResponder (new IPEndPoint (IPAddress.Loopback, 8000), 
266                                         new SocketRequestHandler (EchoRequestHandler));
267                                 responder.Start ();
268
269                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
270                                 req.Method = (string) de.Key;
271                                 req.Timeout = 2000;
272                                 req.ReadWriteTimeout = 2000;
273                                 req.KeepAlive = false;
274                                 Stream rs = req.GetRequestStream ();
275                                 rs.Close ();
276                                 using (HttpWebResponse resp = (HttpWebResponse) req.GetResponse ()) {
277                                         StreamReader sr = new StreamReader (resp.GetResponseStream (),
278                                                 Encoding.UTF8);
279                                         string line = sr.ReadLine ();
280                                         sr.Close ();
281                                         Assert.AreEqual (((string) de.Value) + " /test/ HTTP/1.1",
282                                                 line, req.Method);
283                                         resp.Close ();
284                                 }
285                                 responder.Stop ();
286                         }
287                 }
288
289                 [Test]
290                 public void BeginGetRequestStream_Body_NotAllowed ()
291                 {
292                         IPEndPoint ep = new IPEndPoint (IPAddress.Loopback, 8000);
293                         string url = "http://" + IPAddress.Loopback.ToString () + ":8000/test/";
294
295                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (EchoRequestHandler))) {
296                                 responder.Start ();
297
298                                 HttpWebRequest request;
299
300                                 request = (HttpWebRequest) WebRequest.Create (url);
301                                 request.Method = "GET";
302
303                                 try {
304                                         request.BeginGetRequestStream (null, null);
305                                         Assert.Fail ("#A1");
306                                 } catch (ProtocolViolationException ex) {
307                                         // Cannot send a content-body with this
308                                         // verb-type
309                                         Assert.IsNull (ex.InnerException, "#A2");
310                                         Assert.IsNotNull (ex.Message, "#A3");
311                                 }
312
313                                 request = (HttpWebRequest) WebRequest.Create (url);
314                                 request.Method = "HEAD";
315
316                                 try {
317                                         request.BeginGetRequestStream (null, null);
318                                         Assert.Fail ("#B1");
319                                 } catch (ProtocolViolationException ex) {
320                                         // Cannot send a content-body with this
321                                         // verb-type
322                                         Assert.IsNull (ex.InnerException, "#B2");
323                                         Assert.IsNotNull (ex.Message, "#B3");
324                                 }
325                         }
326                 }
327
328                 [Test] // bug #465613
329                 public void BeginGetRequestStream_NoBuffering ()
330                 {
331                         IPEndPoint ep = new IPEndPoint (IPAddress.Loopback, 8002);
332                         string url = "http://" + IPAddress.Loopback.ToString () + ":8002/test/";
333
334                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (EchoRequestHandler))) {
335                                 responder.Start ();
336
337                                 HttpWebRequest req;
338                                 Stream rs;
339                                 IAsyncResult ar;
340
341                                 req = (HttpWebRequest) WebRequest.Create (url);
342                                 req.Method = "POST";
343                                 req.SendChunked = false;
344                                 req.KeepAlive = false;
345                                 req.AllowWriteStreamBuffering = false;
346
347                                 ar = req.BeginGetRequestStream (null, null);
348                                 rs = req.EndGetRequestStream (ar);
349                                 rs.Close ();
350
351                                 req = (HttpWebRequest) WebRequest.Create (url);
352                                 req.Method = "POST";
353                                 req.SendChunked = false;
354                                 req.KeepAlive = true;
355                                 req.AllowWriteStreamBuffering = false;
356
357                                 try {
358                                         req.BeginGetRequestStream (null, null);
359                                         Assert.Fail ("#A1");
360                                 } catch (ProtocolViolationException ex) {
361                                         // When performing a write operation with
362                                         // AllowWriteStreamBuffering set to false,
363                                         // you must either set ContentLength to a
364                                         // non-negative number or set SendChunked
365                                         // to true
366                                         Assert.IsNull (ex.InnerException, "#A2");
367                                         Assert.IsNotNull (ex.Message, "#A3");
368                                 }
369
370                                 req = (HttpWebRequest) WebRequest.Create (url);
371                                 req.Method = "POST";
372                                 req.SendChunked = false;
373                                 req.KeepAlive = true;
374                                 req.AllowWriteStreamBuffering = false;
375                                 req.ContentLength = 0;
376
377                                 ar = req.BeginGetRequestStream (null, null);
378                                 rs = req.EndGetRequestStream (ar);
379                                 rs.Close ();
380                         }
381                 }
382
383                 [Test] // bug #508027
384                 public void BeginGetResponse ()
385                 {
386                         IPEndPoint ep = new IPEndPoint (IPAddress.Loopback, 8003);
387                         string url = "http://" + IPAddress.Loopback.ToString () + ":8003/test/";
388
389                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (EchoRequestHandler))) {
390                                 responder.Start ();
391
392                                 HttpWebRequest req;
393
394                                 req = (HttpWebRequest) WebRequest.Create (url);
395                                 req.Method = "POST";
396                                 req.SendChunked = false;
397                                 req.KeepAlive = false;
398                                 req.AllowWriteStreamBuffering = false;
399                                 req.BeginGetResponse (null, null);
400                                 req.Abort ();
401
402                                 req = (HttpWebRequest) WebRequest.Create (url);
403                                 req.Method = "POST";
404                                 req.SendChunked = true;
405                                 req.KeepAlive = false;
406                                 req.AllowWriteStreamBuffering = false;
407                                 req.BeginGetResponse (null, null);
408                                 req.Abort ();
409
410                                 req = (HttpWebRequest) WebRequest.Create (url);
411                                 req.Method = "POST";
412                                 req.ContentLength = 5;
413                                 req.SendChunked = false;
414                                 req.KeepAlive = false;
415                                 req.AllowWriteStreamBuffering = false;
416                                 req.BeginGetResponse (null, null);
417                                 req.Abort ();
418
419                                 req = (HttpWebRequest) WebRequest.Create (url);
420                                 req.Method = "POST";
421                                 req.SendChunked = false;
422                                 req.KeepAlive = true;
423                                 req.AllowWriteStreamBuffering = false;
424 #if NET_2_0
425                                 req.BeginGetResponse (null, null);
426                                 req.Abort ();
427 #else
428                                 try {
429                                         req.BeginGetResponse (null, null);
430                                 } catch (ProtocolViolationException ex) {
431                                         // Either ContentLength must be set to a non-negative
432                                         // number, or SendChunked set to true in order to perform
433                                         // the write operation when AllowWriteStreamBuffering
434                                         // is disabled
435                                         Assert.IsNull (ex.InnerException, "#A2");
436                                         Assert.IsNotNull (ex.Message, "#A3");
437                                 } finally {
438                                         req.Abort ();
439                                 }
440 #endif
441
442                                 req = (HttpWebRequest) WebRequest.Create (url);
443                                 req.Method = "POST";
444                                 req.SendChunked = false;
445                                 req.KeepAlive = false;
446                                 req.AllowWriteStreamBuffering = false;
447                                 req.ContentLength = 5;
448                                 req.BeginGetResponse (null, null);
449                                 req.Abort ();
450
451                                 req = (HttpWebRequest) WebRequest.Create (url);
452                                 req.Method = "POST";
453                                 req.SendChunked = false;
454                                 req.KeepAlive = true;
455                                 req.AllowWriteStreamBuffering = false;
456                                 req.ContentLength = 5;
457                                 req.BeginGetResponse (null, null);
458                                 req.Abort ();
459
460                                 req = (HttpWebRequest) WebRequest.Create (url);
461                                 req.Method = "GET";
462                                 req.SendChunked = true;
463 #if NET_2_0
464                                 req.BeginGetResponse (null, null);
465                                 req.Abort ();
466 #else
467                                 try {
468                                         req.BeginGetResponse (null, null);
469                                         Assert.Fail ("#B1");
470                                 } catch (ProtocolViolationException ex) {
471                                         // Content-Length cannot be set for a
472                                         // non-write operation
473                                         Assert.IsNull (ex.InnerException, "#B2");
474                                         Assert.IsNotNull (ex.Message, "#B3");
475                                 } finally {
476                                         req.Abort ();
477                                 }
478 #endif
479
480                                 req = (HttpWebRequest) WebRequest.Create (url);
481                                 req.Method = "GET";
482                                 req.ContentLength = 5;
483 #if NET_2_0
484                                 req.BeginGetResponse (null, null);
485                                 req.Abort ();
486 #else
487                                 try {
488                                         req.BeginGetResponse (null, null);
489                                         Assert.Fail ("#C1");
490                                 } catch (ProtocolViolationException ex) {
491                                         // Content-Length cannot be set for a
492                                         // non-write operation
493                                         Assert.IsNull (ex.InnerException, "#C2");
494                                         Assert.IsNotNull (ex.Message, "#C3");
495                                 } finally {
496                                         req.Abort ();
497                                 }
498 #endif
499
500                                 req = (HttpWebRequest) WebRequest.Create (url);
501                                 req.Method = "GET";
502                                 req.ContentLength = 0;
503 #if NET_2_0
504                                 req.BeginGetResponse (null, null);
505                                 req.Abort ();
506 #else
507                                 try {
508                                         req.BeginGetResponse (null, null);
509                                         Assert.Fail ("#D1");
510                                 } catch (ProtocolViolationException ex) {
511                                         // Content-Length cannot be set for a
512                                         // non-write operation
513                                         Assert.IsNull (ex.InnerException, "#D2");
514                                         Assert.IsNotNull (ex.Message, "#D3");
515                                 } finally {
516                                         req.Abort ();
517                                 }
518 #endif
519                         }
520                 }
521
522                 [Test] // bug #429200
523                 public void GetRequestStream ()
524                 {
525                         IPEndPoint ep = new IPEndPoint (IPAddress.Loopback, 8000);
526                         string url = "http://" + IPAddress.Loopback.ToString () + ":8000/test/";
527
528                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (EchoRequestHandler))) {
529                                 responder.Start ();
530
531                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
532                                 req.Method = "POST";
533                                 req.Timeout = 2000;
534                                 req.ReadWriteTimeout = 2000;
535
536                                 Stream rs1 = req.GetRequestStream ();
537                                 Stream rs2 = req.GetRequestStream ();
538
539                                 Assert.IsNotNull (rs1, "#1");
540                                 Assert.AreSame (rs1, rs2, "#2");
541
542                                 rs1.Close ();
543                         }
544                 }
545
546                 [Test] // bug #510661 and #514996
547                 [Category ("NotWorking")]
548                 public void GetRequestStream_Close_NotAllBytesWritten ()
549                 {
550                         IPEndPoint ep = new IPEndPoint (IPAddress.Loopback, 8000);
551                         string url = "http://" + IPAddress.Loopback.ToString () + ":8000/test/";
552
553                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (EchoRequestHandler))) {
554                                 responder.Start ();
555
556                                 HttpWebRequest req;
557                                 Stream rs;
558
559                                 req = (HttpWebRequest) WebRequest.Create (url);
560                                 req.Method = "POST";
561                                 req.ContentLength = 2;
562                                 rs = req.GetRequestStream ();
563                                 try {
564                                         rs.Close ();
565                                         Assert.Fail ("#A1");
566                                 } catch (WebException ex) {
567                                         // The request was aborted: The request was canceled
568                                         Assert.AreEqual (typeof (WebException), ex.GetType (), "#A2");
569                                         Assert.IsNotNull (ex.Message, "#A3");
570                                         Assert.IsNull (ex.Response, "#A4");
571                                         Assert.AreEqual (WebExceptionStatus.RequestCanceled, ex.Status, "#A5");
572
573                                         // Cannot close stream until all bytes are written
574                                         Exception inner = ex.InnerException;
575                                         Assert.IsNotNull (inner, "#A6");
576                                         Assert.AreEqual (typeof (IOException), inner.GetType (), "#A7");
577                                         Assert.IsNull (inner.InnerException, "#A8");
578                                         Assert.IsNotNull (inner.Message, "#A9");
579                                 }
580
581                                 req = (HttpWebRequest) WebRequest.Create (url);
582                                 req.Method = "POST";
583                                 req.ContentLength = 2;
584                                 rs = req.GetRequestStream ();
585                                 rs.WriteByte (0x0d);
586                                 try {
587                                         rs.Close ();
588                                         Assert.Fail ("#B1");
589                                 } catch (WebException ex) {
590                                         // The request was aborted: The request was canceled
591                                         Assert.AreEqual (typeof (WebException), ex.GetType (), "#B2");
592                                         Assert.IsNotNull (ex.Message, "#B3");
593                                         Assert.IsNull (ex.Response, "#B4");
594                                         Assert.AreEqual (WebExceptionStatus.RequestCanceled, ex.Status, "#B5");
595
596                                         // Cannot close stream until all bytes are written
597                                         Exception inner = ex.InnerException;
598                                         Assert.IsNotNull (inner, "#B6");
599                                         Assert.AreEqual (typeof (IOException), inner.GetType (), "#B7");
600                                         Assert.IsNull (inner.InnerException, "#B8");
601                                         Assert.IsNotNull (inner.Message, "#B9");
602                                 }
603
604                                 req = (HttpWebRequest) WebRequest.Create (url);
605                                 req.Method = "POST";
606                                 req.ContentLength = 2;
607                                 rs = req.GetRequestStream ();
608                                 rs.WriteByte (0x0d);
609                                 rs.WriteByte (0x0d);
610                                 rs.Close ();
611                         }
612                 }
613
614                 [Test] // bug #510642
615                 [Category ("NotWorking")]
616                 public void GetRequestStream_Write_Overflow ()
617                 {
618                         IPEndPoint ep = new IPEndPoint (IPAddress.Loopback, 8001);
619                         string url = "http://" + IPAddress.Loopback.ToString () + ":8001/test/";
620
621                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (EchoRequestHandler))) {
622                                 responder.Start ();
623
624                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
625                                 req.ProtocolVersion = HttpVersion.Version11;
626                                 req.Method = "POST";
627                                 req.Timeout = 200;
628                                 req.ReadWriteTimeout = 100;
629                                 req.ContentLength = 2;
630
631                                 Stream rs = req.GetRequestStream ();
632
633                                 byte [] buffer = new byte [] { 0x2a, 0x2c, 0x1d };
634                                 try {
635                                         rs.Write (buffer, 0, 3);
636                                         Assert.Fail ("#1");
637                                 } catch (ProtocolViolationException ex) {
638                                         // Bytes to be written to the stream exceed
639                                         // Content-Length bytes size specified
640                                         Assert.IsNull (ex.InnerException, "#2");
641                                         Assert.IsNotNull (ex.Message, "#3");
642                                 } finally {
643                                         req.Abort ();
644                                 }
645                         }
646                 }
647
648                 [Test]
649                 [Ignore ("This test asserts that our code violates RFC 2616")]
650                 public void GetRequestStream_Body_NotAllowed ()
651                 {
652                         string [] methods = new string [] { "GET", "HEAD", "CONNECT",
653                                 "get", "HeAd", "ConNect" };
654
655                         foreach (string method in methods) {
656                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (
657                                         "http://localhost:8000");
658                                 req.Method = method;
659                                 try {
660                                         req.GetRequestStream ();
661                                         Assert.Fail ("#1:" + method);
662                                 } catch (ProtocolViolationException ex) {
663                                         Assert.AreEqual (typeof (ProtocolViolationException), ex.GetType (), "#2:" + method);
664                                         Assert.IsNull (ex.InnerException, "#3:" + method);
665                                         Assert.IsNotNull (ex.Message, "#4:" + method);
666                                 }
667                         }
668                 }
669
670                 [Test]
671 #if TARGET_JVM
672                 [Category("NotWorking")]
673 #endif
674                 [Ignore ("This does not timeout any more. That's how MS works when reading small responses")]
675                 public void ReadTimeout ()
676                 {
677                         IPEndPoint localEP = new IPEndPoint (IPAddress.Loopback, 8764);
678                         string url = "http://" + localEP.ToString () + "/original/";
679
680                         using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (RedirectRequestHandler))) {
681                                 responder.Start ();
682
683                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
684                                 req.Method = "POST";
685                                 req.AllowAutoRedirect = false;
686                                 req.Timeout = 200;
687                                 req.ReadWriteTimeout = 100;
688                                 req.KeepAlive = false;
689                                 Stream rs = req.GetRequestStream ();
690                                 rs.Close ();
691                                 using (HttpWebResponse resp = (HttpWebResponse) req.GetResponse ()) {
692                                         try {
693                                                 Stream s = resp.GetResponseStream ();
694                                                 s.ReadByte ();
695                                                 Assert.Fail ("#1");
696                                         } catch (WebException ex) {
697                                                 Assert.AreEqual (typeof (WebException), ex.GetType (), "#2");
698                                                 Assert.IsNull (ex.InnerException, "#3");
699                                                 Assert.IsNull (ex.Response, "#4");
700                                                 Assert.AreEqual (WebExceptionStatus.Timeout, ex.Status, "#5");
701                                         }
702                                 }
703                                 responder.Stop ();
704                         }
705                 }
706
707                 [Test] // bug #324300
708 #if TARGET_JVM
709                 [Category("NotWorking")]
710 #endif
711                 public void AllowAutoRedirect ()
712                 {
713                         IPEndPoint localEP = new IPEndPoint (IPAddress.Loopback, 8764);
714                         string url = "http://" + localEP.ToString () + "/original/";
715
716                         // allow autoredirect
717                         using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (RedirectRequestHandler))) {
718                                 responder.Start ();
719
720                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
721                                 req.Method = "POST";
722                                 req.Timeout = 2000;
723                                 req.ReadWriteTimeout = 2000;
724                                 req.KeepAlive = false;
725                                 Stream rs = req.GetRequestStream ();
726                                 rs.Close ();
727                                 using (HttpWebResponse resp = (HttpWebResponse) req.GetResponse ()) {
728                                         StreamReader sr = new StreamReader (resp.GetResponseStream (),
729                                                 Encoding.UTF8);
730                                         string body = sr.ReadToEnd ();
731
732                                         Assert.AreEqual (resp.StatusCode, HttpStatusCode.OK, "#A1");
733                                         Assert.AreEqual (resp.ResponseUri.ToString (), "http://" +
734                                                 localEP.ToString () + "/moved/", "#A2");
735                                         Assert.AreEqual ("GET", resp.Method, "#A3");
736                                         Assert.AreEqual ("LOOKS OK", body, "#A4");
737                                 }
738                                 responder.Stop ();
739                         }
740
741                         // do not allow autoredirect
742                         using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (RedirectRequestHandler))) {
743                                 responder.Start ();
744
745                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
746                                 req.Method = "POST";
747                                 req.AllowAutoRedirect = false;
748                                 req.Timeout = 1000;
749                                 req.ReadWriteTimeout = 1000;
750                                 req.KeepAlive = false;
751                                 Stream rs = req.GetRequestStream ();
752                                 rs.Close ();
753                                 using (HttpWebResponse resp = (HttpWebResponse) req.GetResponse ()) {
754                                         Assert.AreEqual (resp.StatusCode, HttpStatusCode.Found, "#B1");
755                                         Assert.AreEqual (url, resp.ResponseUri.ToString (), "#B2");
756                                         Assert.AreEqual ("POST", resp.Method, "#B3");
757                                 }
758                                 responder.Stop ();
759                         }
760                 }
761
762                 [Test] // bug #324347
763                 [Category ("NotWorking")]
764                 public void InternalServerError ()
765                 {
766                         IPEndPoint localEP = new IPEndPoint (IPAddress.Loopback, 8764);
767                         string url = "http://" + localEP.ToString () + "/original/";
768
769                         // POST
770                         using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (InternalErrorHandler))) {
771                                 responder.Start ();
772
773                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
774                                 req.Method = "POST";
775                                 req.Timeout = 2000;
776                                 req.ReadWriteTimeout = 2000;
777                                 req.KeepAlive = false;
778                                 Stream rs = req.GetRequestStream ();
779                                 rs.Close ();
780
781                                 try {
782                                         req.GetResponse ();
783                                         Assert.Fail ("#A1");
784                                 } catch (WebException ex) {
785                                         Assert.AreEqual (typeof (WebException), ex.GetType (), "#A2");
786                                         Assert.IsNull (ex.InnerException, "#A3");
787                                         Assert.IsNotNull (ex.Message, "#A4");
788                                         Assert.AreEqual (WebExceptionStatus.ProtocolError, ex.Status, "#A5");
789
790                                         HttpWebResponse webResponse = ex.Response as HttpWebResponse;
791                                         Assert.IsNotNull (webResponse, "#A6");
792                                         Assert.AreEqual ("POST", webResponse.Method, "#A7");
793                                         webResponse.Close ();
794                                 }
795
796                                 responder.Stop ();
797                         }
798
799                         // GET
800                         using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (InternalErrorHandler))) {
801                                 responder.Start ();
802
803                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
804                                 req.Method = "GET";
805                                 req.Timeout = 2000;
806                                 req.ReadWriteTimeout = 2000;
807                                 req.KeepAlive = false;
808
809                                 try {
810                                         req.GetResponse ();
811                                         Assert.Fail ("#B1");
812                                 } catch (WebException ex) {
813                                         Assert.AreEqual (typeof (WebException), ex.GetType (), "#B2");
814                                         Assert.IsNull (ex.InnerException, "#B3");
815                                         Assert.AreEqual (WebExceptionStatus.ProtocolError, ex.Status, "#B4");
816
817                                         HttpWebResponse webResponse = ex.Response as HttpWebResponse;
818                                         Assert.IsNotNull (webResponse, "#B5");
819                                         Assert.AreEqual ("GET", webResponse.Method, "#B6");
820                                         webResponse.Close ();
821                                 }
822
823                                 responder.Stop ();
824                         }
825                 }
826
827                 [Test]
828                 [Category ("NotWorking")] // #B3 fails; we get a SocketException: An existing connection was forcibly closed by the remote host
829                 public void NoContentLength ()
830                 {
831                         IPEndPoint localEP = new IPEndPoint (IPAddress.Loopback, 8764);
832                         string url = "http://" + localEP.ToString () + "/original/";
833
834                         // POST
835                         using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (NoContentLengthHandler))) {
836                                 responder.Start ();
837
838                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
839                                 req.Method = "POST";
840                                 req.Timeout = 2000;
841                                 req.ReadWriteTimeout = 2000;
842                                 req.KeepAlive = false;
843                                 Stream rs = req.GetRequestStream ();
844                                 rs.Close ();
845
846                                 try {
847                                         req.GetResponse ();
848                                         Assert.Fail ("#A1");
849                                 } catch (WebException ex) {
850 #if NET_2_0
851                                         // The underlying connection was closed:
852                                         // An unexpected error occurred on a
853                                         // receive
854                                         Assert.AreEqual (typeof (WebException), ex.GetType (), "#A2");
855                                         Assert.IsNotNull (ex.InnerException, "#A3");
856                                         Assert.AreEqual (WebExceptionStatus.ReceiveFailure, ex.Status, "#A4");
857                                         Assert.AreEqual (typeof (IOException), ex.InnerException.GetType (), "#A5");
858                                         
859                                         // Unable to read data from the transport connection:
860                                         // A connection attempt failed because the connected party
861                                         // did not properly respond after a period of time, or
862                                         // established connection failed because connected host has
863                                         // failed to respond
864                                         IOException ioe = (IOException) ex.InnerException;
865                                         Assert.IsNotNull (ioe.InnerException, "#A6");
866                                         Assert.IsNotNull (ioe.Message, "#A7");
867                                         Assert.AreEqual (typeof (SocketException), ioe.InnerException.GetType (), "#A8");
868
869                                         // An existing connection was forcibly
870                                         // closed by the remote host
871                                         SocketException soe = (SocketException) ioe.InnerException;
872                                         Assert.IsNull (soe.InnerException, "#A9");
873                                         Assert.IsNotNull (soe.Message, "#A10");
874
875                                         HttpWebResponse webResponse = ex.Response as HttpWebResponse;
876                                         Assert.IsNull (webResponse, "#A11");
877 #else
878                                         // The remote server returned an error:
879                                         // (500) Internal Server Error
880                                         Assert.AreEqual (typeof (WebException), ex.GetType (), "#A2");
881                                         Assert.IsNull (ex.InnerException, "#A3");
882                                         Assert.AreEqual (WebExceptionStatus.ProtocolError, ex.Status, "#A4");
883
884                                         HttpWebResponse webResponse = ex.Response as HttpWebResponse;
885                                         Assert.IsNotNull (webResponse, "#A5");
886                                         Assert.AreEqual ("POST", webResponse.Method, "#A6");
887                                         webResponse.Close ();
888 #endif
889                                 }
890
891                                 responder.Stop ();
892                         }
893
894                         // GET
895                         using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (NoContentLengthHandler))) {
896                                 responder.Start ();
897
898                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
899                                 req.Method = "GET";
900                                 req.Timeout = 2000;
901                                 req.ReadWriteTimeout = 2000;
902                                 req.KeepAlive = false;
903
904                                 try {
905                                         req.GetResponse ();
906                                         Assert.Fail ("#B1");
907                                 } catch (WebException ex) {
908                                         // The remote server returned an error:
909                                         // (500) Internal Server Error
910                                         Assert.AreEqual (typeof (WebException), ex.GetType (), "#B2");
911                                         Assert.IsNull (ex.InnerException, "#B3");
912                                         Assert.AreEqual (WebExceptionStatus.ProtocolError, ex.Status, "#B4");
913
914                                         HttpWebResponse webResponse = ex.Response as HttpWebResponse;
915                                         Assert.IsNotNull (webResponse, "#B5");
916                                         Assert.AreEqual ("GET", webResponse.Method, "#B6");
917                                         webResponse.Close ();
918                                 }
919
920                                 responder.Stop ();
921                         }
922                 }
923
924                 [Test] // bug #513087
925                 public void NonStandardVerb ()
926                 {
927                         IPEndPoint ep = new IPEndPoint (IPAddress.Loopback, 8000);
928                         string url = "http://" + IPAddress.Loopback.ToString () + ":8000/moved/";
929
930                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (VerbEchoHandler))) {
931                                 responder.Start ();
932
933                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
934                                 req.Method = "WhatEver";
935                                 req.KeepAlive = false;
936                                 req.Timeout = 20000;
937                                 req.ReadWriteTimeout = 20000;
938
939                                 Stream rs = req.GetRequestStream ();
940                                 rs.Close ();
941
942                                 using (HttpWebResponse resp = (HttpWebResponse) req.GetResponse ()) {
943                                         StreamReader sr = new StreamReader (resp.GetResponseStream (),
944                                                 Encoding.UTF8);
945                                         string body = sr.ReadToEnd ();
946
947                                         Assert.AreEqual (resp.StatusCode, HttpStatusCode.OK, "#1");
948                                         Assert.AreEqual (resp.ResponseUri.ToString (), "http://" +
949                                                 ep.ToString () + "/moved/", "#2");
950                                         Assert.AreEqual ("WhatEver", resp.Method, "#3");
951                                         Assert.AreEqual ("WhatEver", body, "#4");
952                                 }
953
954                                 responder.Stop ();
955                         }
956                 }
957
958                 [Test]
959                 [Category ("NotWorking")] // Assert #2 fails
960                 public void NotModiedSince ()
961                 {
962                         IPEndPoint ep = new IPEndPoint (IPAddress.Loopback, 8000);
963                         string url = "http://" + IPAddress.Loopback.ToString () + ":8000/test/";
964
965                         using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (NotModifiedSinceHandler))) {
966                                 responder.Start ();
967
968                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
969                                 req.Method = "GET";
970                                 req.KeepAlive = false;
971                                 req.Timeout = 20000;
972                                 req.ReadWriteTimeout = 20000;
973 #if NET_2_0
974                                 req.Headers.Add (HttpRequestHeader.IfNoneMatch, "898bbr2347056cc2e096afc66e104653");
975 #else
976                                 req.Headers.Add ("If-None-Match", "898bbr2347056cc2e096afc66e104653");
977 #endif
978                                 req.IfModifiedSince = new DateTime (2010, 01, 04);
979
980                                 DateTime start = DateTime.Now;
981                                 HttpWebResponse response = null;
982
983                                 try {
984                                         req.GetResponse ();
985                                         Assert.Fail ("#1");
986                                 } catch (WebException e) {
987                                         response = (HttpWebResponse) e.Response;
988                                 }
989
990                                 Assert.IsNotNull (response, "#2");
991                                 using (Stream stream = response.GetResponseStream ()) {
992                                         byte [] buffer = new byte [4096];
993                                         int bytesRead = stream.Read (buffer, 0, buffer.Length);
994                                         Assert.AreEqual (0, bytesRead, "#3");
995                                 }
996
997                                 TimeSpan elapsed = DateTime.Now - start;
998                                 Assert.IsTrue (elapsed.TotalMilliseconds < 2000, "#4");
999
1000                                 responder.Stop ();
1001                         }
1002                 }
1003
1004 #if NET_2_0
1005                 [Test] // bug #324182
1006 #if TARGET_JVM
1007                 [Category ("NotWorking")]
1008 #endif
1009                 public void Stream_CanTimeout ()
1010                 {
1011                         IPEndPoint localEP = new IPEndPoint (IPAddress.Loopback, 8764);
1012                         string url = "http://" + localEP.ToString () + "/original/";
1013
1014                         // allow autoredirect
1015                         using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (RedirectRequestHandler))) {
1016                                 responder.Start ();
1017
1018                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
1019                                 req.Method = "POST";
1020                                 req.Timeout = 2000;
1021                                 req.ReadWriteTimeout = 2000;
1022                                 req.KeepAlive = false;
1023                                 Stream rs = req.GetRequestStream ();
1024                                 Assert.IsTrue (rs.CanTimeout, "#1");
1025                                 rs.Close ();
1026                                 using (HttpWebResponse resp = (HttpWebResponse) req.GetResponse ()) {
1027                                         Stream os = resp.GetResponseStream ();
1028                                         Assert.IsTrue (os.CanTimeout, "#2");
1029                                         os.Close ();
1030                                 }
1031                                 responder.Stop ();
1032                         }
1033                 }
1034 #endif
1035
1036                 [Test] // bug #353495
1037                 [Category ("NotWorking")]
1038                 public void LastModifiedKind ()
1039                 {
1040                         const string reqURL = "http://coffeefaq.com/site/node/25";
1041                         HttpWebRequest req = (HttpWebRequest) WebRequest.Create (reqURL);
1042                         HttpWebResponse resp = (HttpWebResponse) req.GetResponse ();
1043                         DateTime lastMod = resp.LastModified;
1044                         string rawLastMod = resp.Headers ["Last-Modified"];
1045                         resp.Close ();
1046                         //Assert.AreEqual ("Tue, 15 Jan 2008 08:59:59 GMT", rawLastMod, "#1");
1047 #if NET_2_0
1048                         Assert.AreEqual (DateTimeKind.Local, lastMod.Kind, "#2");
1049 #endif
1050                         req = (HttpWebRequest) WebRequest.Create (reqURL);
1051                         req.IfModifiedSince = lastMod;
1052                         try {
1053                                 resp = (HttpWebResponse) req.GetResponse ();
1054                                 resp.Close ();
1055                                 Assert.Fail ("Should result in 304");
1056                         } catch (WebException ex) {
1057                                 Assert.AreEqual (WebExceptionStatus.ProtocolError, ex.Status, "#3");
1058                                 Assert.AreEqual (((HttpWebResponse) ex.Response).StatusCode, HttpStatusCode.NotModified, "#4");
1059                         }
1060                 }
1061
1062                 static byte [] EchoRequestHandler (Socket socket)
1063                 {
1064                         MemoryStream ms = new MemoryStream ();
1065                         byte [] buffer = new byte [4096];
1066                         int bytesReceived = socket.Receive (buffer);
1067                         while (bytesReceived > 0) {
1068                                 ms.Write (buffer, 0, bytesReceived);
1069                                 if (socket.Available > 0) {
1070                                         bytesReceived = socket.Receive (buffer);
1071                                 } else {
1072                                         bytesReceived = 0;
1073                                 }
1074                         }
1075                         ms.Flush ();
1076                         ms.Position = 0;
1077                         StreamReader sr = new StreamReader (ms, Encoding.UTF8);
1078                         string request = sr.ReadToEnd ();
1079
1080                         StringWriter sw = new StringWriter ();
1081                         sw.WriteLine ("HTTP/1.1 200 OK");
1082                         sw.WriteLine ("Content-Type: text/xml");
1083                         sw.WriteLine ("Content-Length: " + request.Length.ToString (CultureInfo.InvariantCulture));
1084                         sw.WriteLine ();
1085                         sw.Write (request);
1086                         sw.Flush ();
1087
1088                         return Encoding.UTF8.GetBytes (sw.ToString ());
1089                 }
1090
1091                 static byte [] RedirectRequestHandler (Socket socket)
1092                 {
1093                         MemoryStream ms = new MemoryStream ();
1094                         byte [] buffer = new byte [4096];
1095                         int bytesReceived = socket.Receive (buffer);
1096                         while (bytesReceived > 0) {
1097                                 ms.Write (buffer, 0, bytesReceived);
1098                                 if (socket.Available > 0) {
1099                                         bytesReceived = socket.Receive (buffer);
1100                                 } else {
1101                                         bytesReceived = 0;
1102                                 }
1103                         }
1104                         ms.Flush ();
1105                         ms.Position = 0;
1106                         string statusLine = null;
1107                         using (StreamReader sr = new StreamReader (ms, Encoding.UTF8)) {
1108                                 statusLine = sr.ReadLine ();
1109                         }
1110
1111                         StringWriter sw = new StringWriter ();
1112                         if (statusLine.StartsWith ("POST /original/")) {
1113                                 sw.WriteLine ("HTTP/1.0 302 Found");
1114                                 sw.WriteLine ("Location: " + "http://" + IPAddress.Loopback.ToString () + ":8764/moved/");
1115                                 sw.WriteLine ();
1116                                 sw.Flush ();
1117                         } else if (statusLine.StartsWith ("GET /moved/")) {
1118                                 sw.WriteLine ("HTTP/1.0 200 OK");
1119                                 sw.WriteLine ("Content-Type: text/plain");
1120                                 sw.WriteLine ("Content-Length: 8");
1121                                 sw.WriteLine ();
1122                                 sw.Write ("LOOKS OK");
1123                                 sw.Flush ();
1124                         } else {
1125                                 sw.WriteLine ("HTTP/1.0 500 Too Lazy");
1126                                 sw.WriteLine ();
1127                                 sw.Flush ();
1128                         }
1129
1130                         return Encoding.UTF8.GetBytes (sw.ToString ());
1131                 }
1132
1133                 static byte [] InternalErrorHandler (Socket socket)
1134                 {
1135                         StringWriter sw = new StringWriter ();
1136                         sw.WriteLine ("HTTP/1.1 500 Too Lazy");
1137                         sw.WriteLine ("Content-Length: 0");
1138                         sw.WriteLine ();
1139                         sw.Flush ();
1140
1141                         return Encoding.UTF8.GetBytes (sw.ToString ());
1142                 }
1143
1144                 static byte [] NoContentLengthHandler (Socket socket)
1145                 {
1146                         StringWriter sw = new StringWriter ();
1147                         sw.WriteLine ("HTTP/1.1 500 Too Lazy");
1148                         sw.WriteLine ();
1149                         sw.Flush ();
1150
1151                         return Encoding.UTF8.GetBytes (sw.ToString ());
1152                 }
1153
1154                 static byte [] NotModifiedSinceHandler (Socket socket)
1155                 {
1156                         StringWriter sw = new StringWriter ();
1157                         sw.WriteLine ("HTTP/1.1 304 Not Modified");
1158                         sw.WriteLine ("Date: Fri, 06 Feb 2009 12:50:26 GMT");
1159                         sw.WriteLine ("Server: Apache/2.2.6 (Debian) PHP/5.2.6-2+b1 with Suhosin-Patch mod_ssl/2.2.6 OpenSSL/0.9.8g");
1160                         sw.WriteLine ("Not-Modified-Since: Sun, 08 Feb 2009 08:49:26 GMT");
1161                         sw.WriteLine ("ETag: 898bbr2347056cc2e096afc66e104653");
1162                         sw.WriteLine ("Connection: close");
1163                         sw.WriteLine ();
1164                         sw.Flush ();
1165
1166                         return Encoding.UTF8.GetBytes (sw.ToString ());
1167                 }
1168
1169                 static byte [] VerbEchoHandler (Socket socket)
1170                 {
1171                         MemoryStream ms = new MemoryStream ();
1172                         byte [] buffer = new byte [4096];
1173                         int bytesReceived = socket.Receive (buffer);
1174                         while (bytesReceived > 0) {
1175                                 ms.Write (buffer, 0, bytesReceived);
1176                                 if (socket.Available > 0) {
1177                                         bytesReceived = socket.Receive (buffer);
1178                                 } else {
1179                                         bytesReceived = 0;
1180                                 }
1181                         }
1182                         ms.Flush ();
1183                         ms.Position = 0;
1184                         string statusLine = null;
1185                         using (StreamReader sr = new StreamReader (ms, Encoding.UTF8)) {
1186                                 statusLine = sr.ReadLine ();
1187                         }
1188
1189                         string verb = "DEFAULT";
1190                         if (statusLine != null) {
1191                                 string [] parts = statusLine.Split (' ');
1192                                 if (parts.Length > 0)
1193                                         verb = parts [0];
1194                         }
1195
1196                         StringWriter sw = new StringWriter ();
1197                         sw.WriteLine ("HTTP/1.1 200 OK");
1198                         sw.WriteLine ("Content-Type: text/plain");
1199                         sw.WriteLine ("Content-Length: " + verb.Length);
1200                         sw.WriteLine ();
1201                         sw.Write (verb);
1202                         sw.Flush ();
1203
1204                         return Encoding.UTF8.GetBytes (sw.ToString ());
1205                 }
1206
1207                 [Test]
1208                 public void NtlmAuthentication ()
1209                 {
1210                         NtlmServer server = new NtlmServer ();
1211                         server.Start ();
1212
1213                         string url = String.Format ("http://{0}:{1}/nothing.html", server.IPAddress, server.Port);
1214                         HttpWebRequest request = (HttpWebRequest) WebRequest.Create (url);
1215                         request.Timeout = 5000;
1216                         request.Credentials = new NetworkCredential ("user", "password", "domain");
1217                         HttpWebResponse resp = (HttpWebResponse) request.GetResponse ();
1218                         string res = null;
1219                         using (StreamReader reader = new StreamReader (resp.GetResponseStream ())) {
1220                                 res = reader.ReadToEnd ();      
1221                         }
1222                         resp.Close ();
1223                         server.Stop ();
1224                         Assert.AreEqual ("OK", res);
1225                 }
1226
1227                 class NtlmServer : HttpServer {
1228                         public string Where = "";
1229                         protected override void Run ()
1230                         {
1231                                 Where = "before accept";
1232                                 Socket client = sock.Accept ();
1233                                 NetworkStream ns = new NetworkStream (client, false);
1234                                 StreamReader reader = new StreamReader (ns, Encoding.ASCII);
1235                                 string line;
1236                                 Where = "first read";
1237                                 while ((line = reader.ReadLine ()) != null) {
1238                                         if (line.Trim () == String.Empty) {
1239                                                 break;
1240                                         }
1241                                 }
1242                                 Where = "first write";
1243                                 StreamWriter writer = new StreamWriter (ns, Encoding.ASCII);
1244                                 writer.Write (  "HTTP/1.1 401 Unauthorized\r\n" +
1245                                                 "WWW-Authenticate: NTLM\r\n" +
1246                                                 "Content-Length: 5\r\n\r\nWRONG");
1247
1248                                 writer.Flush ();
1249                                 Where = "second read";
1250                                 while ((line = reader.ReadLine ()) != null) {
1251                                         if (line.Trim () == String.Empty) {
1252                                                 break;
1253                                         }
1254                                 }
1255                                 Where = "second write";
1256                                 writer.Write (  "HTTP/1.1 401 Unauthorized\r\n" +
1257                                                 "WWW-Authenticate: NTLM TlRMTVNTUAACAAAAAAAAADgAAAABggAC8GDhqIONH3sAAAAAAAAAAAAAAAA4AAAABQLODgAAAA8=\r\n" +
1258                                                 "Content-Length: 5\r\n\r\nWRONG");
1259                                 writer.Flush ();
1260
1261                                 Where = "third read";
1262                                 while ((line = reader.ReadLine ()) != null) {
1263                                         if (line.Trim () == String.Empty) {
1264                                                 break;
1265                                         }
1266                                 }
1267                                 Where = "third write";
1268                                 writer.Write (  "HTTP/1.1 200 OK\r\n" +
1269                                                 "Keep-Alive: true\r\n" +
1270                                                 "Content-Length: 2\r\n\r\nOK");
1271                                 writer.Flush ();
1272                                 Thread.Sleep (1000);
1273                                 writer.Close ();
1274                                 reader.Close ();
1275                                 client.Close ();
1276                         }
1277                 }
1278
1279                 class BadChunkedServer : HttpServer {
1280                         protected override void Run ()
1281                         {
1282                                 Socket client = sock.Accept ();
1283                                 NetworkStream ns = new NetworkStream (client, true);
1284                                 StreamWriter writer = new StreamWriter (ns, Encoding.ASCII);
1285                                 writer.Write (  "HTTP/1.1 200 OK\r\n" +
1286                                                 "Transfer-Encoding: chunked\r\n" +
1287                                                 "Connection: close\r\n" +
1288                                                 "Content-Type: text/plain; charset=UTF-8\r\n\r\n");
1289
1290                                 // This body lacks a 'last-chunk' (see RFC 2616)
1291                                 writer.Write ("10\r\n1234567890123456\r\n");
1292                                 writer.Flush ();
1293                                 client.Shutdown (SocketShutdown.Send);
1294                                 Thread.Sleep (1000);
1295                                 writer.Close ();
1296                         }
1297                 }
1298
1299                 class AcceptAllPolicy : ICertificatePolicy {
1300                         public bool CheckValidationResult (ServicePoint sp, X509Certificate certificate, WebRequest request, int error)
1301                         {
1302                                 return true;
1303                         }
1304                 }
1305
1306                 abstract class HttpServer
1307                 {
1308                         protected Socket sock;
1309                         protected Exception error;
1310                         protected ManualResetEvent evt;
1311
1312                         public HttpServer ()
1313                         {
1314                                 sock = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
1315                                 sock.Bind (new IPEndPoint (IPAddress.Loopback, 0));
1316                                 sock.Listen (1);
1317                         }
1318
1319                         public void Start ()
1320                         {
1321                                 evt = new ManualResetEvent (false);
1322                                 Thread th = new Thread (new ThreadStart (Run));
1323                                 th.Start ();
1324                         }
1325
1326                         public void Stop ()
1327                         {
1328                                 evt.Set ();
1329                                 sock.Close ();
1330                         }
1331                         
1332                         public IPAddress IPAddress {
1333                                 get { return ((IPEndPoint) sock.LocalEndPoint).Address; }
1334                         }
1335                         
1336                         public int Port {
1337                                 get { return ((IPEndPoint) sock.LocalEndPoint).Port; }
1338                         }
1339
1340                         public Exception Error { 
1341                                 get { return error; }
1342                         }
1343
1344                         protected abstract void Run ();
1345                 }
1346
1347 #if !TARGET_JVM
1348                 class SslHttpServer : HttpServer {
1349                         X509Certificate _certificate;
1350
1351                         protected override void Run ()
1352                         {
1353                                 try {
1354                                         Socket client = sock.Accept ();
1355                                         NetworkStream ns = new NetworkStream (client, true);
1356                                         SslServerStream s = new SslServerStream (ns, Certificate, false, false);
1357                                         s.PrivateKeyCertSelectionDelegate += new PrivateKeySelectionCallback (GetPrivateKey);
1358
1359                                         StreamReader reader = new StreamReader (s);
1360                                         StreamWriter writer = new StreamWriter (s, Encoding.ASCII);
1361
1362                                         string line;
1363                                         string hello = "<html><body><h1>Hello World!</h1></body></html>";
1364                                         string answer = "HTTP/1.0 200\r\n" +
1365                                                         "Connection: close\r\n" +
1366                                                         "Content-Type: text/html\r\n" +
1367                                                         "Content-Encoding: " + Encoding.ASCII.WebName + "\r\n" +
1368                                                         "Content-Length: " + hello.Length + "\r\n" +
1369                                                         "\r\n" + hello;
1370
1371                                         // Read the headers
1372                                         do {
1373                                                 line = reader.ReadLine ();
1374                                         } while (line != "" && line != null && line.Length > 0);
1375
1376                                         // Now the content. We know it's 100 bytes.
1377                                         // This makes BeginRead in sslclientstream block.
1378                                         char [] cs = new char [100];
1379                                         reader.Read (cs, 0, 100);
1380
1381                                         writer.Write (answer);
1382                                         writer.Flush ();
1383                                         evt.WaitOne (50000, false);
1384                                 } catch (Exception e) {
1385                                         error = e;
1386                                 }
1387                         }
1388
1389                         X509Certificate Certificate {
1390                                 get {
1391                                         if (_certificate == null)
1392                                                 _certificate = new X509Certificate (CertData.Certificate);
1393
1394                                         return _certificate;
1395                                 }
1396                         }
1397
1398                         AsymmetricAlgorithm GetPrivateKey (X509Certificate certificate, string targetHost)
1399                         {
1400                                 PrivateKey key = new PrivateKey (CertData.PrivateKey, null);
1401                                 return key.RSA;
1402                         }
1403                 }
1404
1405                 class CertData {
1406                         public readonly static byte [] Certificate = {
1407                                 48, 130, 1, 191, 48, 130, 1, 40, 160, 3, 2, 1, 2, 2, 16, 36, 
1408                                 14, 97, 190, 146, 132, 208, 71, 175, 6, 87, 168, 185, 175, 55, 43, 48, 
1409                                 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 4, 5, 0, 48, 18, 
1410                                 49, 16, 48, 14, 6, 3, 85, 4, 3, 19, 7, 103, 111, 110, 122, 97, 
1411                                 108, 111, 48, 30, 23, 13, 48, 53, 48, 54, 50, 50, 49, 57, 51, 48, 
1412                                 52, 54, 90, 23, 13, 51, 57, 49, 50, 51, 49, 50, 51, 53, 57, 53, 
1413                                 57, 90, 48, 18, 49, 16, 48, 14, 6, 3, 85, 4, 3, 19, 7, 103, 
1414                                 111, 110, 122, 97, 108, 111, 48, 129, 158, 48, 13, 6, 9, 42, 134, 72, 
1415                                 134, 247, 13, 1, 1, 1, 5, 0, 3, 129, 140, 0, 48, 129, 136, 2, 
1416                                 129, 129, 0, 138, 9, 38, 25, 166, 252, 59, 26, 39, 184, 128, 216, 38, 
1417                                 73, 41, 86, 30, 228, 160, 205, 41, 135, 115, 223, 44, 62, 42, 198, 178, 
1418                                 190, 81, 11, 25, 21, 216, 49, 179, 130, 246, 52, 97, 175, 212, 94, 157, 
1419                                 231, 162, 66, 161, 103, 63, 204, 83, 141, 172, 119, 97, 225, 206, 98, 101, 
1420                                 210, 106, 2, 206, 81, 90, 173, 47, 41, 199, 209, 241, 177, 177, 96, 207, 
1421                                 254, 220, 190, 66, 180, 153, 0, 209, 14, 178, 69, 194, 3, 37, 116, 239, 
1422                                 49, 23, 185, 245, 255, 126, 35, 85, 246, 56, 244, 107, 117, 24, 14, 57, 
1423                                 9, 111, 147, 189, 220, 142, 57, 104, 153, 193, 205, 19, 14, 22, 157, 16, 
1424                                 24, 80, 201, 2, 2, 0, 17, 163, 23, 48, 21, 48, 19, 6, 3, 85, 
1425                                 29, 37, 4, 12, 48, 10, 6, 8, 43, 6, 1, 5, 5, 7, 3, 1, 
1426                                 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 4, 5, 0, 3, 
1427                                 129, 129, 0, 64, 49, 57, 253, 218, 198, 229, 51, 189, 12, 154, 225, 183, 
1428                                 160, 147, 90, 113, 172, 69, 122, 28, 77, 97, 215, 231, 194, 150, 29, 196, 
1429                                 65, 95, 218, 99, 142, 111, 79, 205, 109, 76, 32, 92, 220, 76, 88, 53, 
1430                                 237, 80, 11, 85, 44, 91, 21, 210, 12, 34, 223, 234, 18, 187, 136, 62, 
1431                                 26, 240, 103, 180, 12, 226, 221, 250, 247, 129, 51, 23, 129, 165, 56, 67, 
1432                                 43, 83, 244, 110, 207, 24, 253, 195, 16, 46, 80, 113, 80, 18, 2, 254, 
1433                                 120, 147, 151, 164, 23, 210, 230, 100, 19, 197, 179, 28, 194, 48, 106, 159, 
1434                                 155, 144, 37, 82, 44, 160, 40, 52, 146, 174, 77, 188, 160, 230, 75, 172, 
1435                                 123, 3, 254, 
1436                         };
1437
1438                         public readonly static byte [] PrivateKey = {
1439                                 30, 241, 181, 176, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 
1440                                 0, 0, 0, 0, 84, 2, 0, 0, 7, 2, 0, 0, 0, 36, 0, 0, 
1441                                 82, 83, 65, 50, 0, 4, 0, 0, 17, 0, 0, 0, 201, 80, 24, 16, 
1442                                 157, 22, 14, 19, 205, 193, 153, 104, 57, 142, 220, 189, 147, 111, 9, 57, 
1443                                 14, 24, 117, 107, 244, 56, 246, 85, 35, 126, 255, 245, 185, 23, 49, 239, 
1444                                 116, 37, 3, 194, 69, 178, 14, 209, 0, 153, 180, 66, 190, 220, 254, 207, 
1445                                 96, 177, 177, 241, 209, 199, 41, 47, 173, 90, 81, 206, 2, 106, 210, 101, 
1446                                 98, 206, 225, 97, 119, 172, 141, 83, 204, 63, 103, 161, 66, 162, 231, 157, 
1447                                 94, 212, 175, 97, 52, 246, 130, 179, 49, 216, 21, 25, 11, 81, 190, 178, 
1448                                 198, 42, 62, 44, 223, 115, 135, 41, 205, 160, 228, 30, 86, 41, 73, 38, 
1449                                 216, 128, 184, 39, 26, 59, 252, 166, 25, 38, 9, 138, 175, 88, 190, 223, 
1450                                 27, 24, 224, 123, 190, 69, 164, 234, 129, 59, 108, 229, 248, 62, 187, 15, 
1451                                 235, 147, 162, 83, 47, 123, 170, 190, 224, 31, 215, 110, 143, 31, 227, 216, 
1452                                 85, 88, 154, 83, 207, 229, 41, 28, 237, 116, 181, 17, 37, 141, 224, 185, 
1453                                 164, 144, 141, 233, 164, 138, 177, 241, 115, 181, 230, 150, 7, 92, 139, 141, 
1454                                 113, 95, 57, 191, 211, 165, 217, 250, 197, 68, 164, 184, 168, 43, 48, 65, 
1455                                 177, 237, 173, 144, 148, 221, 62, 189, 147, 63, 216, 188, 206, 103, 226, 171, 
1456                                 32, 20, 230, 116, 144, 192, 1, 39, 202, 87, 74, 250, 6, 142, 188, 23, 
1457                                 45, 4, 112, 191, 253, 67, 69, 70, 128, 143, 44, 234, 41, 96, 195, 82, 
1458                                 202, 35, 158, 149, 240, 151, 23, 25, 166, 179, 85, 144, 58, 120, 149, 229, 
1459                                 205, 34, 8, 110, 86, 119, 130, 210, 37, 173, 65, 71, 169, 67, 8, 51, 
1460                                 20, 96, 51, 155, 3, 39, 85, 187, 40, 193, 57, 19, 99, 78, 173, 28, 
1461                                 129, 154, 108, 175, 8, 138, 237, 71, 27, 148, 129, 35, 47, 57, 101, 237, 
1462                                 168, 178, 227, 221, 212, 63, 124, 254, 253, 215, 183, 159, 49, 103, 74, 49, 
1463                                 67, 160, 171, 72, 194, 215, 108, 251, 178, 18, 184, 100, 211, 105, 21, 186, 
1464                                 39, 66, 218, 154, 72, 222, 90, 237, 179, 251, 51, 224, 212, 56, 251, 6, 
1465                                 209, 151, 198, 176, 89, 110, 35, 141, 248, 237, 223, 68, 135, 206, 207, 169, 
1466                                 254, 219, 243, 130, 71, 11, 94, 113, 233, 92, 63, 156, 169, 72, 215, 110, 
1467                                 95, 94, 191, 50, 59, 89, 187, 59, 183, 99, 161, 146, 233, 245, 219, 80, 
1468                                 87, 113, 251, 50, 144, 195, 158, 46, 189, 232, 119, 91, 75, 22, 6, 176, 
1469                                 39, 206, 25, 196, 213, 195, 219, 24, 28, 103, 104, 36, 137, 128, 4, 119, 
1470                                 163, 40, 126, 87, 18, 86, 128, 243, 213, 101, 2, 237, 78, 64, 160, 55, 
1471                                 199, 93, 90, 126, 175, 199, 55, 89, 234, 190, 5, 16, 196, 88, 28, 208, 
1472                                 28, 92, 32, 115, 204, 9, 202, 101, 15, 123, 43, 75, 90, 144, 95, 179, 
1473                                 102, 249, 57, 150, 204, 99, 147, 203, 16, 63, 81, 244, 226, 237, 82, 204, 
1474                                 20, 200, 140, 65, 83, 217, 161, 23, 123, 37, 115, 12, 100, 73, 70, 190, 
1475                                 32, 235, 174, 140, 148, 157, 47, 238, 40, 208, 228, 80, 54, 187, 156, 252, 
1476                                 253, 230, 231, 156, 138, 125, 96, 79, 3, 27, 143, 55, 146, 169, 165, 61, 
1477                                 238, 60, 227, 77, 217, 93, 117, 122, 111, 46, 173, 113, 
1478                         };
1479                 }
1480 #endif
1481         }
1482 }