TARGET_JVM: mark some tests with NotWorking under TARGET_JVM
[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]
260                 [Ignore ("This test asserts that our code violates RFC 2616")]
261                 public void GetRequestStream_Body_NotAllowed ()
262                 {
263                         string [] methods = new string [] { "GET", "HEAD", "CONNECT",
264                                 "get", "HeAd", "ConNect" };
265
266                         foreach (string method in methods) {
267                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (
268                                         "http://localhost:8000");
269                                 req.Method = method;
270                                 try {
271                                         req.GetRequestStream ();
272                                         Assert.Fail ("#1:" + method);
273                                 } catch (ProtocolViolationException ex) {
274                                         Assert.AreEqual (typeof (ProtocolViolationException), ex.GetType (), "#2:" + method);
275                                         Assert.IsNull (ex.InnerException, "#3:" + method);
276                                         Assert.IsNotNull (ex.Message, "#4:" + method);
277                                 }
278                         }
279                 }
280
281                 [Test]
282 #if TARGET_JVM
283                 [Category("NotWorking")]
284 #endif
285                 public void ReadTimeout ()
286                 {
287                         IPEndPoint localEP = new IPEndPoint (IPAddress.Loopback, 8764);
288                         string url = "http://" + localEP.ToString () + "/original/";
289
290                         using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (RedirectRequestHandler))) {
291                                 responder.Start ();
292
293                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
294                                 req.Method = "POST";
295                                 req.AllowAutoRedirect = false;
296                                 req.Timeout = 200;
297                                 req.ReadWriteTimeout = 100;
298                                 req.KeepAlive = false;
299                                 Stream rs = req.GetRequestStream ();
300                                 rs.Close ();
301                                 using (HttpWebResponse resp = (HttpWebResponse) req.GetResponse ()) {
302                                         try {
303                                                 Stream s = resp.GetResponseStream ();
304                                                 s.ReadByte ();
305                                                 Assert.Fail ("#1");
306                                         } catch (WebException ex) {
307                                                 Assert.AreEqual (typeof (WebException), ex.GetType (), "#2");
308                                                 Assert.IsNull (ex.InnerException, "#3");
309                                                 Assert.IsNull (ex.Response, "#4");
310                                                 Assert.AreEqual (WebExceptionStatus.Timeout, ex.Status, "#5");
311                                         }
312                                 }
313                                 responder.Stop ();
314                         }
315                 }
316
317                 [Test] // bug #81624
318 #if TARGET_JVM
319                 [Category("NotWorking")]
320 #endif
321                 public void AllowAutoRedirect ()
322                 {
323                         IPEndPoint localEP = new IPEndPoint (IPAddress.Loopback, 8764);
324                         string url = "http://" + localEP.ToString () + "/original/";
325
326                         // allow autoredirect
327                         using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (RedirectRequestHandler))) {
328                                 responder.Start ();
329
330                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
331                                 req.Method = "POST";
332                                 req.Timeout = 2000;
333                                 req.ReadWriteTimeout = 2000;
334                                 req.KeepAlive = false;
335                                 Stream rs = req.GetRequestStream ();
336                                 rs.Close ();
337                                 using (HttpWebResponse resp = (HttpWebResponse) req.GetResponse ()) {
338                                         StreamReader sr = new StreamReader (resp.GetResponseStream (),
339                                                 Encoding.UTF8);
340                                         string body = sr.ReadToEnd ();
341
342                                         Assert.AreEqual (resp.StatusCode, HttpStatusCode.OK, "#A1");
343                                         Assert.AreEqual (resp.ResponseUri.ToString (), "http://" +
344                                                 localEP.ToString () + "/moved/", "#A2");
345                                         Assert.AreEqual ("GET", resp.Method, "#A3");
346                                         Assert.AreEqual ("LOOKS OK", body, "#A4");
347                                 }
348                                 responder.Stop ();
349                         }
350
351                         // do not allow autoredirect
352                         using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (RedirectRequestHandler))) {
353                                 responder.Start ();
354
355                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
356                                 req.Method = "POST";
357                                 req.AllowAutoRedirect = false;
358                                 req.Timeout = 1000;
359                                 req.ReadWriteTimeout = 1000;
360                                 req.KeepAlive = false;
361                                 Stream rs = req.GetRequestStream ();
362                                 rs.Close ();
363                                 using (HttpWebResponse resp = (HttpWebResponse) req.GetResponse ()) {
364                                         Assert.AreEqual (resp.StatusCode, HttpStatusCode.Found, "#B1");
365                                         Assert.AreEqual (url, resp.ResponseUri.ToString (), "#B2");
366                                         Assert.AreEqual ("POST", resp.Method, "#B3");
367                                 }
368                                 responder.Stop ();
369                         }
370                 }
371
372                 [Test] // bug #81671
373                 [Category ("NotWorking")]
374                 public void InternalServerError ()
375                 {
376                         IPEndPoint localEP = new IPEndPoint (IPAddress.Loopback, 8764);
377                         string url = "http://" + localEP.ToString () + "/original/";
378
379                         // POST
380                         using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (InternalErrorHandler))) {
381                                 responder.Start ();
382
383                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
384                                 req.Method = "POST";
385                                 req.Timeout = 2000;
386                                 req.ReadWriteTimeout = 2000;
387                                 req.KeepAlive = false;
388                                 Stream rs = req.GetRequestStream ();
389                                 rs.Close ();
390
391                                 try {
392                                         req.GetResponse ();
393                                         Assert.Fail ("#A1");
394                                 } catch (WebException ex) {
395                                         Assert.AreEqual (typeof (WebException), ex.GetType (), "#A2");
396                                         Assert.IsNull (ex.InnerException, "#A3");
397                                         Assert.IsNotNull (ex.Message, "#A4");
398                                         Assert.AreEqual (WebExceptionStatus.ProtocolError, ex.Status, "#A5");
399
400                                         HttpWebResponse webResponse = ex.Response as HttpWebResponse;
401                                         Assert.IsNotNull (webResponse, "#A6");
402                                         Assert.AreEqual ("POST", webResponse.Method, "#A7");
403                                         webResponse.Close ();
404                                 }
405
406                                 responder.Stop ();
407                         }
408
409                         // GET
410                         using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (InternalErrorHandler))) {
411                                 responder.Start ();
412
413                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
414                                 req.Method = "GET";
415                                 req.Timeout = 2000;
416                                 req.ReadWriteTimeout = 2000;
417                                 req.KeepAlive = false;
418
419                                 try {
420                                         req.GetResponse ();
421                                         Assert.Fail ("#B1");
422                                 } catch (WebException ex) {
423                                         Assert.AreEqual (typeof (WebException), ex.GetType (), "#B2");
424                                         Assert.IsNull (ex.InnerException, "#B3");
425                                         Assert.AreEqual (WebExceptionStatus.ProtocolError, ex.Status, "#B4");
426
427                                         HttpWebResponse webResponse = ex.Response as HttpWebResponse;
428                                         Assert.IsNotNull (webResponse, "#B5");
429                                         Assert.AreEqual ("GET", webResponse.Method, "#B6");
430                                         webResponse.Close ();
431                                 }
432
433                                 responder.Stop ();
434                         }
435                 }
436
437                 [Test]
438                 [Category ("NotWorking")] // we report a timeout
439                 public void NoContentLength ()
440                 {
441                         IPEndPoint localEP = new IPEndPoint (IPAddress.Loopback, 8764);
442                         string url = "http://" + localEP.ToString () + "/original/";
443
444                         // POST
445                         using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (NoContentLengthHandler))) {
446                                 responder.Start ();
447
448                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
449                                 req.Method = "POST";
450                                 req.Timeout = 2000;
451                                 req.ReadWriteTimeout = 2000;
452                                 req.KeepAlive = false;
453                                 Stream rs = req.GetRequestStream ();
454                                 rs.Close ();
455
456                                 try {
457                                         req.GetResponse ();
458                                         Assert.Fail ("#A1");
459                                 } catch (WebException ex) {
460                                         Assert.AreEqual (typeof (WebException), ex.GetType (), "#A2");
461 #if NET_2_0
462                                         //Assert.IsNotNull (ex.InnerException, "#A3");
463                                         Assert.AreEqual (WebExceptionStatus.ReceiveFailure, ex.Status, "#A4");
464                                         Assert.AreEqual (typeof (IOException), ex.InnerException.GetType (), "#A5");
465                                         
466                                         // Unable to read data from the transport connection:
467                                         // A connection attempt failed because the connected party
468                                         // did not properly respond after a period of time, or
469                                         // established connection failed because connected host has
470                                         // failed to respond
471                                         IOException ioe = (IOException) ex.InnerException;
472                                         Assert.IsNotNull (ioe.InnerException, "#A6");
473                                         Assert.IsNotNull (ioe.Message, "#A7");
474                                         Assert.AreEqual (typeof (SocketException), ioe.InnerException.GetType (), "#A8");
475
476                                         // A connection attempt failed because the connected party
477                                         // did not properly respond after a period of time, or
478                                         // established connection failed because connected host has
479                                         // failed to respond
480                                         SocketException soe = (SocketException) ioe.InnerException;
481                                         Assert.IsNull (soe.InnerException, "#A9");
482                                         Assert.IsNotNull (soe.Message, "#A10");
483
484                                         HttpWebResponse webResponse = ex.Response as HttpWebResponse;
485                                         Assert.IsNull (webResponse, "#A11");
486 #else
487                                         Assert.IsNull (ex.InnerException, "#A3");
488                                         Assert.AreEqual (WebExceptionStatus.ProtocolError, ex.Status, "#A4");
489
490                                         HttpWebResponse webResponse = ex.Response as HttpWebResponse;
491                                         Assert.IsNotNull (webResponse, "#A5");
492                                         Assert.AreEqual ("POST", webResponse.Method, "#A6");
493                                         webResponse.Close ();
494 #endif
495                                 }
496
497                                 responder.Stop ();
498                         }
499
500                         // GET
501                         using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (NoContentLengthHandler))) {
502                                 responder.Start ();
503
504                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
505                                 req.Method = "GET";
506                                 req.Timeout = 2000;
507                                 req.ReadWriteTimeout = 2000;
508                                 req.KeepAlive = false;
509
510                                 try {
511                                         req.GetResponse ();
512                                         Assert.Fail ("#B1");
513                                 } catch (WebException ex) {
514                                         Assert.AreEqual (typeof (WebException), ex.GetType (), "#B2");
515                                         Assert.IsNull (ex.InnerException, "#B3");
516                                         Assert.AreEqual (WebExceptionStatus.ProtocolError, ex.Status, "#B4");
517
518                                         HttpWebResponse webResponse = ex.Response as HttpWebResponse;
519                                         Assert.IsNotNull (webResponse, "#B5");
520                                         Assert.AreEqual ("GET", webResponse.Method, "#B6");
521                                         webResponse.Close ();
522                                 }
523
524                                 responder.Stop ();
525                         }
526                 }
527
528 #if NET_2_0
529                 [Test] // bug #81504
530 #if TARGET_JVM
531                 [Category ("NotWorking")]
532 #endif
533                 public void Stream_CanTimeout ()
534                 {
535                         IPEndPoint localEP = new IPEndPoint (IPAddress.Loopback, 8764);
536                         string url = "http://" + localEP.ToString () + "/original/";
537
538                         // allow autoredirect
539                         using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (RedirectRequestHandler))) {
540                                 responder.Start ();
541
542                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
543                                 req.Method = "POST";
544                                 req.Timeout = 2000;
545                                 req.ReadWriteTimeout = 2000;
546                                 req.KeepAlive = false;
547                                 Stream rs = req.GetRequestStream ();
548                                 Assert.IsTrue (rs.CanTimeout, "#1");
549                                 rs.Close ();
550                                 using (HttpWebResponse resp = (HttpWebResponse) req.GetResponse ()) {
551                                         Stream os = resp.GetResponseStream ();
552                                         Assert.IsTrue (os.CanTimeout, "#2");
553                                         os.Close ();
554                                 }
555                                 responder.Stop ();
556                         }
557                 }
558 #endif
559
560                 static byte [] EchoRequestHandler (Socket socket)
561                 {
562                         MemoryStream ms = new MemoryStream ();
563                         byte [] buffer = new byte [4096];
564                         int bytesReceived = socket.Receive (buffer);
565                         while (bytesReceived > 0) {
566                                 ms.Write (buffer, 0, bytesReceived);
567                                 if (socket.Available > 0) {
568                                         bytesReceived = socket.Receive (buffer);
569                                 } else {
570                                         bytesReceived = 0;
571                                 }
572                         }
573                         ms.Flush ();
574                         ms.Position = 0;
575                         StreamReader sr = new StreamReader (ms, Encoding.UTF8);
576                         string request = sr.ReadToEnd ();
577
578                         StringWriter sw = new StringWriter ();
579                         sw.WriteLine ("HTTP/1.1 200 OK");
580                         sw.WriteLine ("Content-Type: text/xml");
581                         sw.WriteLine ("Content-Length: " + request.Length.ToString (CultureInfo.InvariantCulture));
582                         sw.WriteLine ();
583                         sw.Write (request);
584                         sw.Flush ();
585
586                         return Encoding.UTF8.GetBytes (sw.ToString ());
587                 }
588
589                 static byte [] RedirectRequestHandler (Socket socket)
590                 {
591                         MemoryStream ms = new MemoryStream ();
592                         byte [] buffer = new byte [4096];
593                         int bytesReceived = socket.Receive (buffer);
594                         while (bytesReceived > 0) {
595                                 ms.Write (buffer, 0, bytesReceived);
596                                 if (socket.Available > 0) {
597                                         bytesReceived = socket.Receive (buffer);
598                                 } else {
599                                         bytesReceived = 0;
600                                 }
601                         }
602                         ms.Flush ();
603                         ms.Position = 0;
604                         string statusLine = null;
605                         using (StreamReader sr = new StreamReader (ms, Encoding.UTF8)) {
606                                 statusLine = sr.ReadLine ();
607                         }
608
609                         StringWriter sw = new StringWriter ();
610                         if (statusLine.StartsWith ("POST /original/")) {
611                                 sw.WriteLine ("HTTP/1.1 302 Found");
612                                 sw.WriteLine ("Location: " + "http://" + IPAddress.Loopback.ToString () + ":8764/moved/");
613                                 sw.WriteLine ();
614                                 sw.Flush ();
615                         } else if (statusLine.StartsWith ("GET /moved/")) {
616                                 sw.WriteLine ("HTTP/1.1 200 OK");
617                                 sw.WriteLine ("Content-Type: text/plain");
618                                 sw.WriteLine ("Content-Length: 8");
619                                 sw.WriteLine ();
620                                 sw.Write ("LOOKS OK");
621                                 sw.Flush ();
622                         } else {
623                                 sw.WriteLine ("HTTP/1.1 500 Too Lazy");
624                                 sw.WriteLine ();
625                                 sw.Flush ();
626                         }
627
628                         return Encoding.UTF8.GetBytes (sw.ToString ());
629                 }
630
631                 static byte [] InternalErrorHandler (Socket socket)
632                 {
633                         StringWriter sw = new StringWriter ();
634                         sw.WriteLine ("HTTP/1.1 500 Too Lazy");
635                         sw.WriteLine ("Content-Length: 0");
636                         sw.WriteLine ();
637                         sw.Flush ();
638
639                         return Encoding.UTF8.GetBytes (sw.ToString ());
640                 }
641
642                 static byte [] NoContentLengthHandler (Socket socket)
643                 {
644                         StringWriter sw = new StringWriter ();
645                         sw.WriteLine ("HTTP/1.1 500 Too Lazy");
646                         sw.WriteLine ();
647                         sw.Flush ();
648
649                         return Encoding.UTF8.GetBytes (sw.ToString ());
650                 }
651
652                 class BadChunkedServer : HttpServer {
653                         protected override void Run ()
654                         {
655                                 Socket client = sock.Accept ();
656                                 NetworkStream ns = new NetworkStream (client, true);
657                                 StreamWriter writer = new StreamWriter (ns, Encoding.ASCII);
658                                 writer.Write (  "HTTP/1.1 200 OK\r\n" +
659                                                 "Transfer-Encoding: chunked\r\n" +
660                                                 "Connection: close\r\n" +
661                                                 "Content-Type: text/plain; charset=UTF-8\r\n\r\n");
662
663                                 // This body lacks a 'last-chunk' (see RFC 2616)
664                                 writer.Write ("10\r\n1234567890123456\r\n");
665                                 writer.Flush ();
666                                 client.Shutdown (SocketShutdown.Send);
667                                 Thread.Sleep (1000);
668                                 writer.Close ();
669                         }
670                 }
671
672                 class AcceptAllPolicy : ICertificatePolicy {
673                         public bool CheckValidationResult (ServicePoint sp, X509Certificate certificate, WebRequest request, int error)
674                         {
675                                 return true;
676                         }
677                 }
678
679                 abstract class HttpServer
680                 {
681                         protected Socket sock;
682                         protected Exception error;
683                         protected ManualResetEvent evt;
684
685                         public HttpServer ()
686                         {
687                                 sock = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
688                                 sock.Bind (new IPEndPoint (IPAddress.Loopback, 0));
689                                 sock.Listen (1);
690                         }
691
692                         public void Start ()
693                         {
694                                 evt = new ManualResetEvent (false);
695                                 Thread th = new Thread (new ThreadStart (Run));
696                                 th.Start ();
697                         }
698
699                         public void Stop ()
700                         {
701                                 evt.Set ();
702                                 sock.Close ();
703                         }
704                         
705                         public IPAddress IPAddress {
706                                 get { return ((IPEndPoint) sock.LocalEndPoint).Address; }
707                         }
708                         
709                         public int Port {
710                                 get { return ((IPEndPoint) sock.LocalEndPoint).Port; }
711                         }
712
713                         public Exception Error { 
714                                 get { return error; }
715                         }
716
717                         protected abstract void Run ();
718                 }
719
720 #if !TARGET_JVM
721                 class SslHttpServer : HttpServer {
722                         X509Certificate _certificate;
723
724                         protected override void Run ()
725                         {
726                                 try {
727                                         Socket client = sock.Accept ();
728                                         NetworkStream ns = new NetworkStream (client, true);
729                                         SslServerStream s = new SslServerStream (ns, Certificate, false, false);
730                                         s.PrivateKeyCertSelectionDelegate += new PrivateKeySelectionCallback (GetPrivateKey);
731
732                                         StreamReader reader = new StreamReader (s);
733                                         StreamWriter writer = new StreamWriter (s, Encoding.ASCII);
734
735                                         string line;
736                                         string hello = "<html><body><h1>Hello World!</h1></body></html>";
737                                         string answer = "HTTP/1.0 200\r\n" +
738                                                         "Connection: close\r\n" +
739                                                         "Content-Type: text/html\r\n" +
740                                                         "Content-Encoding: " + Encoding.ASCII.WebName + "\r\n" +
741                                                         "Content-Length: " + hello.Length + "\r\n" +
742                                                         "\r\n" + hello;
743
744                                         // Read the headers
745                                         do {
746                                                 line = reader.ReadLine ();
747                                         } while (line != "" && line != null && line.Length > 0);
748
749                                         // Now the content. We know it's 100 bytes.
750                                         // This makes BeginRead in sslclientstream block.
751                                         char [] cs = new char [100];
752                                         reader.Read (cs, 0, 100);
753
754                                         writer.Write (answer);
755                                         writer.Flush ();
756                                         evt.WaitOne (50000, false);
757                                 } catch (Exception e) {
758                                         error = e;
759                                 }
760                         }
761
762                         X509Certificate Certificate {
763                                 get {
764                                         if (_certificate == null)
765                                                 _certificate = new X509Certificate (CertData.Certificate);
766
767                                         return _certificate;
768                                 }
769                         }
770
771                         AsymmetricAlgorithm GetPrivateKey (X509Certificate certificate, string targetHost)
772                         {
773                                 PrivateKey key = new PrivateKey (CertData.PrivateKey, null);
774                                 return key.RSA;
775                         }
776                 }
777
778                 class CertData {
779                         public readonly static byte [] Certificate = {
780                                 48, 130, 1, 191, 48, 130, 1, 40, 160, 3, 2, 1, 2, 2, 16, 36, 
781                                 14, 97, 190, 146, 132, 208, 71, 175, 6, 87, 168, 185, 175, 55, 43, 48, 
782                                 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 4, 5, 0, 48, 18, 
783                                 49, 16, 48, 14, 6, 3, 85, 4, 3, 19, 7, 103, 111, 110, 122, 97, 
784                                 108, 111, 48, 30, 23, 13, 48, 53, 48, 54, 50, 50, 49, 57, 51, 48, 
785                                 52, 54, 90, 23, 13, 51, 57, 49, 50, 51, 49, 50, 51, 53, 57, 53, 
786                                 57, 90, 48, 18, 49, 16, 48, 14, 6, 3, 85, 4, 3, 19, 7, 103, 
787                                 111, 110, 122, 97, 108, 111, 48, 129, 158, 48, 13, 6, 9, 42, 134, 72, 
788                                 134, 247, 13, 1, 1, 1, 5, 0, 3, 129, 140, 0, 48, 129, 136, 2, 
789                                 129, 129, 0, 138, 9, 38, 25, 166, 252, 59, 26, 39, 184, 128, 216, 38, 
790                                 73, 41, 86, 30, 228, 160, 205, 41, 135, 115, 223, 44, 62, 42, 198, 178, 
791                                 190, 81, 11, 25, 21, 216, 49, 179, 130, 246, 52, 97, 175, 212, 94, 157, 
792                                 231, 162, 66, 161, 103, 63, 204, 83, 141, 172, 119, 97, 225, 206, 98, 101, 
793                                 210, 106, 2, 206, 81, 90, 173, 47, 41, 199, 209, 241, 177, 177, 96, 207, 
794                                 254, 220, 190, 66, 180, 153, 0, 209, 14, 178, 69, 194, 3, 37, 116, 239, 
795                                 49, 23, 185, 245, 255, 126, 35, 85, 246, 56, 244, 107, 117, 24, 14, 57, 
796                                 9, 111, 147, 189, 220, 142, 57, 104, 153, 193, 205, 19, 14, 22, 157, 16, 
797                                 24, 80, 201, 2, 2, 0, 17, 163, 23, 48, 21, 48, 19, 6, 3, 85, 
798                                 29, 37, 4, 12, 48, 10, 6, 8, 43, 6, 1, 5, 5, 7, 3, 1, 
799                                 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 4, 5, 0, 3, 
800                                 129, 129, 0, 64, 49, 57, 253, 218, 198, 229, 51, 189, 12, 154, 225, 183, 
801                                 160, 147, 90, 113, 172, 69, 122, 28, 77, 97, 215, 231, 194, 150, 29, 196, 
802                                 65, 95, 218, 99, 142, 111, 79, 205, 109, 76, 32, 92, 220, 76, 88, 53, 
803                                 237, 80, 11, 85, 44, 91, 21, 210, 12, 34, 223, 234, 18, 187, 136, 62, 
804                                 26, 240, 103, 180, 12, 226, 221, 250, 247, 129, 51, 23, 129, 165, 56, 67, 
805                                 43, 83, 244, 110, 207, 24, 253, 195, 16, 46, 80, 113, 80, 18, 2, 254, 
806                                 120, 147, 151, 164, 23, 210, 230, 100, 19, 197, 179, 28, 194, 48, 106, 159, 
807                                 155, 144, 37, 82, 44, 160, 40, 52, 146, 174, 77, 188, 160, 230, 75, 172, 
808                                 123, 3, 254, 
809                         };
810
811                         public readonly static byte [] PrivateKey = {
812                                 30, 241, 181, 176, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 
813                                 0, 0, 0, 0, 84, 2, 0, 0, 7, 2, 0, 0, 0, 36, 0, 0, 
814                                 82, 83, 65, 50, 0, 4, 0, 0, 17, 0, 0, 0, 201, 80, 24, 16, 
815                                 157, 22, 14, 19, 205, 193, 153, 104, 57, 142, 220, 189, 147, 111, 9, 57, 
816                                 14, 24, 117, 107, 244, 56, 246, 85, 35, 126, 255, 245, 185, 23, 49, 239, 
817                                 116, 37, 3, 194, 69, 178, 14, 209, 0, 153, 180, 66, 190, 220, 254, 207, 
818                                 96, 177, 177, 241, 209, 199, 41, 47, 173, 90, 81, 206, 2, 106, 210, 101, 
819                                 98, 206, 225, 97, 119, 172, 141, 83, 204, 63, 103, 161, 66, 162, 231, 157, 
820                                 94, 212, 175, 97, 52, 246, 130, 179, 49, 216, 21, 25, 11, 81, 190, 178, 
821                                 198, 42, 62, 44, 223, 115, 135, 41, 205, 160, 228, 30, 86, 41, 73, 38, 
822                                 216, 128, 184, 39, 26, 59, 252, 166, 25, 38, 9, 138, 175, 88, 190, 223, 
823                                 27, 24, 224, 123, 190, 69, 164, 234, 129, 59, 108, 229, 248, 62, 187, 15, 
824                                 235, 147, 162, 83, 47, 123, 170, 190, 224, 31, 215, 110, 143, 31, 227, 216, 
825                                 85, 88, 154, 83, 207, 229, 41, 28, 237, 116, 181, 17, 37, 141, 224, 185, 
826                                 164, 144, 141, 233, 164, 138, 177, 241, 115, 181, 230, 150, 7, 92, 139, 141, 
827                                 113, 95, 57, 191, 211, 165, 217, 250, 197, 68, 164, 184, 168, 43, 48, 65, 
828                                 177, 237, 173, 144, 148, 221, 62, 189, 147, 63, 216, 188, 206, 103, 226, 171, 
829                                 32, 20, 230, 116, 144, 192, 1, 39, 202, 87, 74, 250, 6, 142, 188, 23, 
830                                 45, 4, 112, 191, 253, 67, 69, 70, 128, 143, 44, 234, 41, 96, 195, 82, 
831                                 202, 35, 158, 149, 240, 151, 23, 25, 166, 179, 85, 144, 58, 120, 149, 229, 
832                                 205, 34, 8, 110, 86, 119, 130, 210, 37, 173, 65, 71, 169, 67, 8, 51, 
833                                 20, 96, 51, 155, 3, 39, 85, 187, 40, 193, 57, 19, 99, 78, 173, 28, 
834                                 129, 154, 108, 175, 8, 138, 237, 71, 27, 148, 129, 35, 47, 57, 101, 237, 
835                                 168, 178, 227, 221, 212, 63, 124, 254, 253, 215, 183, 159, 49, 103, 74, 49, 
836                                 67, 160, 171, 72, 194, 215, 108, 251, 178, 18, 184, 100, 211, 105, 21, 186, 
837                                 39, 66, 218, 154, 72, 222, 90, 237, 179, 251, 51, 224, 212, 56, 251, 6, 
838                                 209, 151, 198, 176, 89, 110, 35, 141, 248, 237, 223, 68, 135, 206, 207, 169, 
839                                 254, 219, 243, 130, 71, 11, 94, 113, 233, 92, 63, 156, 169, 72, 215, 110, 
840                                 95, 94, 191, 50, 59, 89, 187, 59, 183, 99, 161, 146, 233, 245, 219, 80, 
841                                 87, 113, 251, 50, 144, 195, 158, 46, 189, 232, 119, 91, 75, 22, 6, 176, 
842                                 39, 206, 25, 196, 213, 195, 219, 24, 28, 103, 104, 36, 137, 128, 4, 119, 
843                                 163, 40, 126, 87, 18, 86, 128, 243, 213, 101, 2, 237, 78, 64, 160, 55, 
844                                 199, 93, 90, 126, 175, 199, 55, 89, 234, 190, 5, 16, 196, 88, 28, 208, 
845                                 28, 92, 32, 115, 204, 9, 202, 101, 15, 123, 43, 75, 90, 144, 95, 179, 
846                                 102, 249, 57, 150, 204, 99, 147, 203, 16, 63, 81, 244, 226, 237, 82, 204, 
847                                 20, 200, 140, 65, 83, 217, 161, 23, 123, 37, 115, 12, 100, 73, 70, 190, 
848                                 32, 235, 174, 140, 148, 157, 47, 238, 40, 208, 228, 80, 54, 187, 156, 252, 
849                                 253, 230, 231, 156, 138, 125, 96, 79, 3, 27, 143, 55, 146, 169, 165, 61, 
850                                 238, 60, 227, 77, 217, 93, 117, 122, 111, 46, 173, 113, 
851                         };
852                 }
853 #endif
854         }
855 }