952546c8aa7d085530e9b3e6b76d0397c90770bb
[mono.git] / mcs / class / System / Test / System.Net / HttpListener2Test.cs
1 //
2 // HttpListener2Test.cs
3 //      - Unit tests for System.Net.HttpListener - connection testing
4 //
5 // Author:
6 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 //
8 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29 #if NET_2_0
30 using System;
31 using System.Collections.Generic;
32 using System.Globalization;
33 using System.IO;
34 using System.Net;
35 using System.Net.Sockets;
36 using System.Text;
37 using System.Threading;
38 using NUnit.Framework;
39
40 // ***************************************************************************************
41 // NOTE: when adding prefixes, make then unique per test, as MS might take 'some time' to
42 // unregister it even after explicitly closing the listener.
43 // ***************************************************************************************
44 namespace MonoTests.System.Net {
45         [TestFixture]
46 #if TARGET_JVM  
47         [Ignore ("The class HttpListener is not supported")]
48 #endif
49         public class HttpListener2Test {
50                 public class MyNetworkStream : NetworkStream {
51                         public MyNetworkStream (Socket sock) : base (sock, true)
52                         {
53                         }
54
55                         public Socket GetSocket ()
56                         {
57                                 return Socket;
58                         }
59                 }
60
61                 public static HttpListener CreateAndStartListener (string prefix)
62                 {
63                         HttpListener listener = new HttpListener ();
64                         listener.Prefixes.Add (prefix);
65                         listener.Start ();
66                         return listener;
67                 }
68
69                 public static HttpListener CreateAndStartListener (string prefix, AuthenticationSchemes authSchemes)
70                 {
71                         HttpListener listener = new HttpListener ();
72                         listener.AuthenticationSchemes = authSchemes;
73                         listener.Prefixes.Add (prefix);
74                         listener.Start ();
75                         return listener;
76                 }
77
78                 public static MyNetworkStream CreateNS (int port)
79                 {
80                         Socket sock = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
81                         sock.Connect (new IPEndPoint (IPAddress.Loopback, port));
82                         return new MyNetworkStream (sock);
83                 }
84
85                 public static void Send (Stream stream, string str)
86                 {
87                         byte [] bytes = Encoding.ASCII.GetBytes (str);
88                         stream.Write (bytes, 0, bytes.Length);
89                 }
90
91                 public static string Receive (Stream stream, int size)
92                 {
93                         byte [] bytes = new byte [size];
94                         int nread = stream.Read (bytes, 0, size);
95                         return Encoding.ASCII.GetString (bytes, 0, nread);
96                 }
97
98                 public static string ReceiveWithTimeout (Stream stream, int size, int timeout, out bool timed_out)
99                 {
100                         byte [] bytes = new byte [size];
101                         IAsyncResult ares = stream.BeginRead (bytes, 0, size, null, null);
102                         timed_out = !ares.AsyncWaitHandle.WaitOne (timeout, false);
103                         if (timed_out)
104                                 return null;
105                         int nread = stream.EndRead (ares);
106                         return Encoding.ASCII.GetString (bytes, 0, nread);
107                 }
108
109                 public static HttpListenerContext GetContextWithTimeout (HttpListener listener, int timeout, out bool timed_out)
110                 {
111                         IAsyncResult ares = listener.BeginGetContext (null, null);
112                         timed_out = !ares.AsyncWaitHandle.WaitOne (timeout, false);
113                         if (timed_out)
114                                 return null;
115                         return listener.EndGetContext (ares);
116                 }
117
118                 [Test]
119                 public void Test1 ()
120                 {
121                         HttpListener listener = CreateAndStartListener ("http://127.0.0.1:9000/test1/");
122                         NetworkStream ns = CreateNS (9000);
123                         Send (ns, "GET / HTTP/1.1\r\n\r\n"); // No host
124                         string response = Receive (ns, 512);
125                         ns.Close ();
126                         listener.Close ();
127                         Assert.IsTrue (response.StartsWith ("HTTP/1.1 400"));
128                 }
129
130                 [Test]
131                 public void Test2 ()
132                 {
133                         HttpListener listener = CreateAndStartListener ("http://127.0.0.1:9000/test2/");
134                         NetworkStream ns = CreateNS (9000);
135                         Send (ns, "GET / HTTP/1.1\r\nHost: 127.0.0.1\r\n\r\n"); // no prefix
136                         string response = Receive (ns, 512);
137                         ns.Close ();
138                         listener.Close ();
139                         Assert.IsTrue (response.StartsWith ("HTTP/1.1 400"));
140                 }
141
142                 [Test]
143                 public void Test3 ()
144                 {
145                         StringBuilder bad = new StringBuilder ();
146                         for (int i = 0; i < 33; i++){
147                                 if (i != 13)
148                                         bad.Append ((char) i);
149                         }
150                         bad.Append ('(');
151                         bad.Append (')');
152                         bad.Append ('[');
153                         bad.Append (']');
154                         bad.Append ('<');
155                         bad.Append ('>');
156                         bad.Append ('@');
157                         bad.Append (',');
158                         bad.Append (';');
159                         bad.Append (':');
160                         bad.Append ('\\');
161                         bad.Append ('"');
162                         bad.Append ('/');
163                         bad.Append ('?');
164                         bad.Append ('=');
165                         bad.Append ('{');
166                         bad.Append ('}');
167
168                         foreach (char b in bad.ToString ()){
169                                 HttpListener listener = CreateAndStartListener ("http://127.0.0.1:9000/test3/");
170                                 NetworkStream ns = CreateNS (9000);
171                                 Send (ns, String.Format ("MA{0} / HTTP/1.1\r\nHost: 127.0.0.1\r\n\r\n", b)); // bad method
172                                 
173                                 string response = Receive (ns, 512);
174                                 ns.Close ();
175                                 listener.Close ();
176                                 Assert.AreEqual (true, response.StartsWith ("HTTP/1.1 400"), String.Format ("Failed on {0}", (int) b));
177                         }
178                 }
179
180                 [Test]
181                 public void Test4 ()
182                 {
183                         HttpListener listener = CreateAndStartListener ("http://127.0.0.1:9000/test4/");
184                         NetworkStream ns = CreateNS (9000);
185                         Send (ns, "POST /test4/ HTTP/1.1\r\nHost: 127.0.0.1\r\n\r\n"); // length required
186                         string response = Receive (ns, 512);
187                         ns.Close ();
188                         listener.Close ();
189                         Assert.IsTrue (response.StartsWith ("HTTP/1.1 411"));
190                 }
191
192                 [Test]
193                 public void Test5 ()
194                 {
195                         HttpListener listener = CreateAndStartListener ("http://127.0.0.1:9000/test5/");
196                         NetworkStream ns = CreateNS (9000);
197                         Send (ns, "POST / HTTP/1.1\r\nHost: 127.0.0.1\r\nTransfer-Encoding: pepe\r\n\r\n"); // not implemented
198                         string response = Receive (ns, 512);
199                         ns.Close ();
200                         listener.Close ();
201                         Assert.IsTrue (response.StartsWith ("HTTP/1.1 501"));
202                 }
203
204                 [Test]
205                 public void Test6 ()
206                 {
207                         HttpListener listener = CreateAndStartListener ("http://127.0.0.1:9000/test6/");
208                         NetworkStream ns = CreateNS (9000);
209                          // not implemented! This is against the RFC. Should be a bad request/length required
210                         Send (ns, "POST /test6/ HTTP/1.1\r\nHost: 127.0.0.1\r\nTransfer-Encoding: identity\r\n\r\n");
211                         string response = Receive (ns, 512);
212                         ns.Close ();
213                         listener.Close ();
214                         Assert.IsTrue (response.StartsWith ("HTTP/1.1 501"));
215                 }
216
217                 [Test]
218                 public void Test7 ()
219                 {
220                         HttpListener listener = CreateAndStartListener ("http://127.0.0.1:9000/test7/");
221                         NetworkStream ns = CreateNS (9000);
222                         Send (ns, "POST /test7/ HTTP/1.1\r\nHost: 127.0.0.1\r\nContent-Length: 3\r\n\r\n123");
223                         HttpListenerContext ctx = listener.GetContext ();
224                         Send (ctx.Response.OutputStream, "%%%OK%%%");
225                         string response = Receive (ns, 1024);
226                         ns.Close ();
227                         listener.Close ();
228                         Assert.IsTrue (response.StartsWith ("HTTP/1.1 200"));
229                         Assert.IsTrue (-1 != response.IndexOf ("Transfer-Encoding: chunked"));
230                 }
231
232                 [Test]
233                 public void Test8 ()
234                 {
235                         HttpListener listener = CreateAndStartListener ("http://127.0.0.1:9000/test8/");
236                         NetworkStream ns = CreateNS (9000);
237                         // Just like Test7, but 1.0
238                         Send (ns, "POST /test8/ HTTP/1.0\r\nHost: 127.0.0.1\r\nContent-Length: 3\r\n\r\n123");
239                         HttpListenerContext ctx = listener.GetContext ();
240                         Send (ctx.Response.OutputStream, "%%%OK%%%");
241                         string response = Receive (ns, 512);
242                         ns.Close ();
243                         listener.Close ();
244                         Assert.IsTrue (response.StartsWith ("HTTP/1.1 200"));
245                         Assert.IsTrue (-1 == response.IndexOf ("Transfer-Encoding: chunked"));
246                 }
247
248                 [Test]
249                 public void Test9 ()
250                 {
251                         // 1.0 + "Transfer-Encoding: chunked"
252                         HttpListener listener = CreateAndStartListener ("http://127.0.0.1:9000/test9/");
253                         NetworkStream ns = CreateNS (9000);
254                         Send (ns, "POST /test9/ HTTP/1.0\r\nHost: 127.0.0.1\r\nTransfer-Encoding: chunked\r\n\r\n3\r\n123\r\n0\r\n\r\n");
255                         bool timeout;
256                         string response = ReceiveWithTimeout (ns, 512, 1000, out timeout);
257                         Assert.IsFalse (timeout);
258                         listener.Close ();
259                         ns.Close ();
260                         Assert.IsTrue (response.StartsWith ("HTTP/1.1 411"));
261                 }
262
263                 [Test]
264                 public void Test10 ()
265                 {
266                         // Same as Test9, but now we shutdown the socket for sending.
267                         HttpListener listener = CreateAndStartListener ("http://127.0.0.1:9000/test10/");
268                         MyNetworkStream ns = CreateNS (9000);
269                         Send (ns, "POST /test10/ HTTP/1.0\r\nHost: 127.0.0.1\r\nTransfer-Encoding: chunked\r\n\r\n3\r\n123\r\n0\r\n\r\n");
270                         ns.GetSocket ().Shutdown (SocketShutdown.Send);
271                         bool timeout;
272                         string response = ReceiveWithTimeout (ns, 512, 1000, out timeout);
273                         Assert.IsFalse (timeout);
274                         listener.Close ();
275                         ns.Close ();
276                         Assert.IsTrue (response.StartsWith ("HTTP/1.1 411"));
277                 }
278
279                 [Test]
280                 public void Test11 ()
281                 {
282                         // 0.9
283                         HttpListener listener = CreateAndStartListener ("http://127.0.0.1:9000/test11/");
284                         MyNetworkStream ns = CreateNS (9000);
285                         Send (ns, "POST /test11/ HTTP/0.9\r\nHost: 127.0.0.1\r\n\r\n123");
286                         ns.GetSocket ().Shutdown (SocketShutdown.Send);
287                         string input = Receive (ns, 512);
288                         ns.Close ();
289                         listener.Close ();
290                         Assert.IsTrue (input.StartsWith ("HTTP/1.1 400"));
291                 }
292
293                 [Test]
294                 public void Test12 ()
295                 {
296                         // 0.9
297                         HttpListener listener = CreateAndStartListener ("http://127.0.0.1:9000/test12/");
298                         MyNetworkStream ns = CreateNS (9000);
299                         Send (ns, "POST /test12/ HTTP/0.9\r\nHost: 127.0.0.1\r\nContent-Length: 3\r\n\r\n123");
300                         ns.GetSocket ().Shutdown (SocketShutdown.Send);
301                         string input = Receive (ns, 512);
302                         ns.Close ();
303                         listener.Close ();
304                         Assert.IsTrue (input.StartsWith ("HTTP/1.1 400"));
305                 }
306
307                 [Test]
308                 public void Test13 ()
309                 {
310                         // 0.9
311                         HttpListener listener = CreateAndStartListener ("http://127.0.0.1:9000/test13/");
312                         MyNetworkStream ns = CreateNS (9000);
313                         Send (ns, "GEt /test13/ HTTP/0.9\r\nHost: 127.0.0.1\r\n\r\n");
314                         ns.GetSocket ().Shutdown (SocketShutdown.Send);
315                         string input = Receive (ns, 512);
316                         ns.Close ();
317                         listener.Close ();
318                         Assert.IsTrue (input.StartsWith ("HTTP/1.1 400"));
319                 }
320
321                 HttpListenerRequest test14_request;
322                 ManualResetEvent test_evt;
323                 bool test14_error;
324                 [Test]
325                 public void Test14 ()
326                 {
327                         HttpListener listener = CreateAndStartListener ("http://127.0.0.1:9000/test14/");
328                         MyNetworkStream ns = CreateNS (9000);
329                         Send (ns, "POST /test14/ HTTP/1.0\r\nHost: 127.0.0.1\r\nContent-Length: 3\r\n\r\n123");
330                         HttpListenerContext c = listener.GetContext ();
331                         test14_request = c.Request;
332                         test_evt = new ManualResetEvent (false);
333                         Thread thread = new Thread (ReadToEnd);
334                         thread.Start ();
335                         if (test_evt.WaitOne (3000, false) == false) {
336                                 thread.Abort ();
337                                 test_evt.Close ();
338                                 Assert.IsTrue (false, "Timed out");
339                         }
340                         test_evt.Close ();
341                         Assert.AreEqual ("123", read_to_end, "Did not get the expected input.");
342                         c.Response.Close ();
343                         ns.Close ();
344                 }
345
346                 string read_to_end;
347                 void ReadToEnd ()
348                 {
349                         using (StreamReader r = new StreamReader (test14_request.InputStream)) {
350                                 read_to_end = r.ReadToEnd ();
351                                 test_evt.Set ();
352                         }
353                 }
354
355                 [Test]
356                 public void Test15 ()
357                 {
358                         // 2 separate writes -> 2 packets. Body size > 8kB
359                         HttpListener listener = CreateAndStartListener ("http://127.0.0.1:9000/test15/");
360                         MyNetworkStream ns = CreateNS (9000);
361                         Send (ns, "POST /test15/ HTTP/1.0\r\nHost: 127.0.0.1\r\nContent-Length: 8888\r\n\r\n");
362                         Thread.Sleep (800);
363                         string data = new string ('a', 8888);
364                         Send (ns, data);
365                         HttpListenerContext c = listener.GetContext ();
366                         HttpListenerRequest req = c.Request;
367                         using (StreamReader r = new StreamReader (req.InputStream)) {
368                                 read_to_end = r.ReadToEnd ();
369                         }
370                         Assert.AreEqual (read_to_end.Length, data.Length, "Wrong length");
371                         Assert.IsTrue (data == read_to_end, "Wrong data");
372                         c.Response.Close ();
373                         ns.Close ();
374                 }
375
376                 [Test]
377                 public void Test16 ()
378                 {
379                         // 1 single write with headers + body (size > 8kB)
380                         HttpListener listener = CreateAndStartListener ("http://127.0.0.1:9000/test16/");
381                         MyNetworkStream ns = CreateNS (9000);
382                         StringBuilder sb = new StringBuilder ();
383                         sb.Append ("POST /test16/ HTTP/1.0\r\nHost: 127.0.0.1\r\nContent-Length: 8888\r\n\r\n");
384                         string eights = new string ('b', 8888);
385                         sb.Append (eights);
386                         string data = sb.ToString ();
387                         Send (ns, data);
388                         HttpListenerContext c = listener.GetContext ();
389                         HttpListenerRequest req = c.Request;
390                         using (StreamReader r = new StreamReader (req.InputStream)) {
391                                 read_to_end = r.ReadToEnd ();
392                         }
393                         Assert.AreEqual (read_to_end.Length, read_to_end.Length, "Wrong length");
394                         Assert.IsTrue (eights == read_to_end, "Wrong data");
395                         c.Response.Close ();
396                         ns.Close ();
397                 }
398
399                 [Test]
400                 public void Test17 ()
401                 {
402                         HttpListener listener = CreateAndStartListener ("http://127.0.0.1:9000/test17/");
403                         NetworkStream ns = CreateNS (9000);
404                         Send (ns, "RANDOM /test17/ HTTP/1.1\r\nHost: 127.0.0.1\r\nContent-Length: 3\r\n\r\n123");
405                         HttpListenerContext ctx = listener.GetContext ();
406                         Send (ctx.Response.OutputStream, "%%%OK%%%");
407                         string response = Receive (ns, 1024);
408                         ns.Close ();
409                         listener.Close ();
410                         Assert.IsTrue (response.StartsWith ("HTTP/1.1 200"));
411                         Assert.IsTrue (-1 != response.IndexOf ("Transfer-Encoding: chunked"));
412                 }
413
414                 [Test]
415                 public void Test_MultipleClosesOnOuputStreamAllowed ()
416                 {
417                         HttpListener listener = CreateAndStartListener ("http://127.0.0.1:9000/MultipleCloses/");
418                         NetworkStream ns = CreateNS (9000);
419                         Send (ns, "GET /MultipleCloses/ HTTP/1.1\r\nHost: 127.0.0.1\r\n\r\n");
420
421                         HttpListenerContext ctx = listener.GetContext ();
422                         ctx.Response.OutputStream.Close ();
423                         ctx.Response.OutputStream.Close ();
424                         ctx.Response.OutputStream.Close ();
425                         ctx.Response.Close ();
426                         listener.Close ();
427                 }
428         
429                 void SendCookie ()
430                 {
431                         NetworkStream ns = CreateNS (9000);
432                         Send (ns, "GET /SendCookie/ HTTP/1.1\r\nHost: 127.0.0.1\r\n"+
433                                 "Cookie:$Version=\"1\"; "+
434                                 "Cookie1=Value1; $Path=\"/\"; "+
435                                 "CookieM=ValueM; $Path=\"/p2\"; $Domain=\"test\"; $Port=\"99\";"+
436                                 "Cookie2=Value2; $Path=\"/foo\";"+
437                                 "\r\n"+
438                                 "\r\n");
439                         ns.Flush ();
440                         Thread.Sleep (200);
441                         ns.Close();
442                 }
443
444                 [Test]
445                 public void ReceiveCookiesFromClient ()
446                 {
447                         HttpListener listener = CreateAndStartListener ("http://127.0.0.1:9000/SendCookie/");
448                         Thread clientThread = new Thread (new ThreadStart (SendCookie));
449                         clientThread.Start ();
450
451                         HttpListenerContext context = listener.GetContext();
452                         HttpListenerRequest request = context.Request;
453
454                         Assert.AreEqual (3, request.Cookies.Count, "#1");
455                         foreach (Cookie c in request.Cookies) {
456                                 if (c.Name == "Cookie1") {
457                                         Assert.AreEqual ("Value1", c.Value, "#2");
458                                         Assert.AreEqual ("\"/\"", c.Path, "#3");
459                                         Assert.AreEqual (0, c.Port.Length, "#4");
460                                         Assert.AreEqual (0, c.Domain.Length, "#5");
461                                 } else if (c.Name == "CookieM") {
462                                         Assert.AreEqual ("ValueM", c.Value, "#6");
463                                         Assert.AreEqual ("\"/p2\"", c.Path, "#7");
464                                         Assert.AreEqual ("\"99\"", c.Port, "#8");
465                                         Assert.AreEqual ("\"test\"", c.Domain, "#9");
466                                 } else if (c.Name == "Cookie2") {
467                                         Assert.AreEqual ("Value2", c.Value, "#10");
468                                         Assert.AreEqual ("\"/foo\"", c.Path, "#11");
469                                         Assert.AreEqual (0, c.Port.Length, "#12");
470                                         Assert.AreEqual (0, c.Domain.Length, "#13");
471                                 } else
472                                         Assert.Fail ("Invalid cookie name " + c.Name);
473                         }
474
475                         listener.Close ();
476                 }
477
478                 private object _lock = new Object();
479                 private string cookieResponse;
480
481                 void ReceiveCookie () {
482                         lock (_lock) {
483                                 NetworkStream ns = CreateNS (9000);
484                                 Send (ns, "GET /ReceiveCookie/ HTTP/1.1\r\nHost: 127.0.0.1\r\n\r\n");
485                                 cookieResponse = Receive (ns, 512);
486                         }
487                 }
488
489                 [Test]
490                 public void SendCookiestoClient ()
491                 {
492                         HttpListener listener = CreateAndStartListener ("http://127.0.0.1:9000/ReceiveCookie/");
493                         Thread clientThread = new Thread (new ThreadStart (ReceiveCookie));
494                         clientThread.Start ();
495
496                         HttpListenerContext context = listener.GetContext();
497                         HttpListenerRequest request = context.Request;
498                         HttpListenerResponse response = context.Response;
499
500                         Cookie cookie = new Cookie ();
501                         cookie.Name = "Name0";
502                         cookie.Value = "Value0";
503                         cookie.Domain = "blue";
504                         cookie.Path = "/path/";
505                         cookie.Port = "\"80\"";
506                         cookie.Version = 1;
507                         response.Cookies.Add (cookie);
508
509                         string responseString = "<HTML><BODY>----</BODY></HTML>";
510                         byte[] buffer = Encoding.UTF8.GetBytes(responseString);
511                         response.ContentLength64 = buffer.Length;
512                         Stream output = response.OutputStream;
513                         output.Write(buffer, 0, buffer.Length);
514                         output.Flush ();
515                         response.Close();
516                         
517                         lock (_lock) {
518                                 bool foundCookie = false;
519                                 foreach (String str in cookieResponse.Split ('\n')) {
520                                         if (!str.StartsWith ("Set-Cookie2"))
521                                                 continue;
522                                         Dictionary<string, String> dic = new Dictionary<string, String>();
523                                         foreach (String p in str.Substring (str.IndexOf (":") + 1).Split (';')) {
524                                                 String[] parts = p.Split('=');
525                                                 dic.Add (parts [0].Trim (), parts [1].Trim ());
526                                         }
527                                         Assert.AreEqual ("Value0", dic ["Name0"], "#1");
528                                         Assert.AreEqual ("blue", dic ["Domain"], "#2");
529                                         Assert.AreEqual ("\"/path/\"", dic ["Path"], "#3");
530                                         Assert.AreEqual ("\"80\"", dic ["Port"], "#4");
531                                         Assert.AreEqual ("1", dic ["Version"], "#5");
532                                         foundCookie = true;
533                                         break;
534                                 }
535                                 Assert.IsTrue (foundCookie, "#6");
536                         }
537
538                         listener.Close ();
539                 }
540
541                 [Test]
542                 public void MultiResponses ()
543                 {
544                         Thread srv = new Thread (new ThreadStart (EchoServer));
545                         srv.Start ();
546                         Thread.Sleep (200);
547
548                         for (int i = 0; i < 10; i++) {
549                                 string payload = string.Format (CultureInfo.InvariantCulture,
550                                         "Client{0}", i);
551
552                                 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (
553                                         "http://localhost:8888/foobar/");
554                                 req.ServicePoint.Expect100Continue = false;
555                                 req.ServicePoint.UseNagleAlgorithm = false;
556                                 req.Method = "POST";
557                                 StreamWriter w = new StreamWriter (req.GetRequestStream ());
558                                 w.WriteLine (payload);
559                                 w.Close ();
560
561                                 HttpWebResponse resp = (HttpWebResponse) req.GetResponse ();
562                                 StreamReader r = new StreamReader (resp.GetResponseStream ());
563                                 Assert.AreEqual ("Hello, " + payload + "!", r.ReadToEnd ().Trim ());
564                                 r.Close ();
565                         }
566
567                         manualReset.Set ();
568                         srv.Join ();
569                 }
570
571                 void EchoServer ()
572                 {
573                         HttpListener listener = new HttpListener ();
574                         listener.Prefixes.Add ("http://*:8888/foobar/");
575                         listener.Start ();
576
577                         manualReset = new ManualResetEvent (false);
578
579                         IAsyncResult result = listener.BeginGetContext (
580                                 new AsyncCallback (EchoCallback), listener);
581                         manualReset.WaitOne ();
582                 }
583
584                 void EchoCallback (IAsyncResult result)
585                 {
586                         HttpListener listener = (HttpListener) result.AsyncState;
587                         HttpListenerContext context = listener.EndGetContext (result);
588                         HttpListenerRequest req = context.Request;
589                         StreamReader r = new StreamReader (req.InputStream);
590                         string reqBody = r.ReadToEnd ().Trim ();
591
592                         HttpListenerResponse resp = context.Response;
593                         StreamWriter o = new StreamWriter (resp.OutputStream);
594                         o.WriteLine ("Hello, " + reqBody + "!");
595                         o.Close ();
596
597                         listener.BeginGetContext (new AsyncCallback (EchoCallback), listener);
598                 }
599
600                 private ManualResetEvent manualReset;
601
602         }
603
604         [TestFixture]
605         public class HttpListenerBugs {
606                 [Test]
607                 public void TestNonChunkedAsync ()
608                 {
609                         HttpListener listener = HttpListener2Test.CreateAndStartListener ("http://127.0.0.1:9123/");
610
611                         listener.BeginGetContext (callback, listener);
612                         
613                         HttpListener2Test.MyNetworkStream ns = HttpListener2Test.CreateNS (9123);
614                         string message = "<script>\n"+
615                                 " <!-- register the blueprint for our show-headers service -->\n"+
616                                 " <action verb=\"POST\" path=\"/host/register\">\n" +
617                                 "    <blueprint>\n" +
618                                 "      <assembly>dream.tutorial.show-headers</assembly>\n" +
619                                 "      <class>MindTouch.Dream.Tutorial.ShowHeadersService</class>\n" +
620                                 "    </blueprint>\n" +
621                                 "  </action>\n" +
622                                 "\n" +
623                                 "  <!-- instantiate it -->\n" +
624                                 "  <action verb=\"POST\" path=\"/host/start\">\n" +
625                                 "    <config>\n" +
626                                 "      <path>show-headers</path>\n" +
627                                 "      <class>MindTouch.Dream.Tutorial.ShowHeadersService</class>\n" +
628                                 "    </config>\n" +
629                                 "  </action>\n" +
630                                 "</script>";
631                         string s = String.Format ("POST / HTTP/1.1\r\nHost: 127.0.0.1\r\nContent-Length: {0}\r\n\r\n{1}",
632                                                 message.Length, message);  
633                         HttpListener2Test.Send (ns, s);
634                         bool timedout;
635                         string response = HttpListener2Test.ReceiveWithTimeout (ns, 1024, 3000, out timedout);
636                         ns.Close ();
637                         Assert.IsFalse (timedout);
638                 }
639
640                 void callback (IAsyncResult ar)
641                 {
642                         HttpListener l = (HttpListener) ar.AsyncState;
643
644                         HttpListenerContext c = l.EndGetContext (ar);
645                         HttpListenerRequest request = c.Request;
646
647                         StreamReader r = new StreamReader (request.InputStream);
648                         string sr =r.ReadToEnd ();
649                         HttpListener2Test.Send (c.Response.OutputStream, "Miguel is love");
650                 }
651         }
652 }
653 #endif
654