2 // HttpWebRequestTest.cs - NUnit Test Cases for System.Net.HttpWebRequest
5 // Lawrence Pit (loz@cable.a2000.nl)
6 // Martin Willemoes Hansen (mwh@sysrq.dk)
7 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
9 // (C) 2003 Martin Willemoes Hansen
10 // Copyright (c) 2005 Novell, Inc. (http://www.novell.com
13 using NUnit.Framework;
15 using System.Collections;
16 using System.Collections.Specialized;
17 using System.Globalization;
20 using System.Net.Sockets;
21 using System.Security.Cryptography;
22 using System.Security.Cryptography.X509Certificates;
24 using System.Threading;
26 using Mono.Security.Authenticode;
27 using Mono.Security.Protocol.Tls;
30 namespace MonoTests.System.Net
33 public class HttpWebRequestTest
37 [Ignore ("Ignore failures in Sys.Net")]
39 public void Proxy_Null ()
41 HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://www.google.com");
42 Assert.IsNotNull (req.Proxy, "#1");
45 Assert.IsNull (req.Proxy, "#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");
61 [Category("InetAccess")]
63 [Ignore ("NMA - wrong cookies number returned")]
67 HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://www.google.com");
68 Assertion.AssertNotNull ("req:If Modified Since: ", req.IfModifiedSince);
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");
74 HttpWebResponse res = (HttpWebResponse) req.GetResponse ();
75 Assert.AreEqual ("OK", res.StatusCode.ToString (), "#B1");
76 Assert.AreEqual ("OK", res.StatusDescription, "#B2");
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");
86 public void AddRange ()
88 HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://www.google.com");
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"]);
95 req.AddRange ("bits", 2000);
96 Assertion.Fail ("#2");
97 } catch (InvalidOperationException) {}
101 [Category("InetAccess")]
102 public void Cookies1 ()
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));
125 #if !TARGET_JVM //NotWorking
127 public void SslClientBlock ()
129 // This tests that the write request/initread/write body sequence does not hang
131 // If there's a regression for this, the test will hang.
132 ServicePointManager.CertificatePolicy = new AcceptAllPolicy ();
134 SslHttpServer server = new SslHttpServer ();
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);
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 ();
151 if (server.Error != null)
154 ServicePointManager.CertificatePolicy = null;
160 [Category("NotWorking")]
162 public void Missing_ContentEncoding ()
164 ServicePointManager.CertificatePolicy = new AcceptAllPolicy ();
166 BadChunkedServer server = new BadChunkedServer ();
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);
176 if (server.Error != null)
179 ServicePointManager.CertificatePolicy = null;
185 [Category ("NotWorking")]
187 public void BadServer_ChunkedClose ()
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 ();
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 ();
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);
209 if (server.Error != null)
212 Assertion.AssertEquals ("1234567890123456", x);
216 [Ignore ("This test asserts that our code violates RFC 2616")]
217 public void MethodCase ()
219 ListDictionary methods = new ListDictionary ();
221 methods.Add ("post", "POST");
222 methods.Add ("puT", "PUT");
224 methods.Add ("post", "post");
225 methods.Add ("puT", "puT");
227 methods.Add ("POST", "POST");
228 methods.Add ("whatever", "whatever");
229 methods.Add ("PUT", "PUT");
231 IPEndPoint ep = new IPEndPoint (IPAddress.Loopback, 8000);
232 string url = "http://" + IPAddress.Loopback.ToString () + ":8000/test/";
234 foreach (DictionaryEntry de in methods) {
235 SocketResponder responder = new SocketResponder (new IPEndPoint (IPAddress.Loopback, 8000),
236 new SocketRequestHandler (EchoRequestHandler));
239 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
240 req.Method = (string) de.Key;
242 req.ReadWriteTimeout = 2000;
243 req.KeepAlive = false;
244 Stream rs = req.GetRequestStream ();
246 using (HttpWebResponse resp = (HttpWebResponse) req.GetResponse ()) {
247 StreamReader sr = new StreamReader (resp.GetResponseStream (),
249 string line = sr.ReadLine ();
251 Assert.AreEqual (((string) de.Value) + " /test/ HTTP/1.1",
259 [Test] // bug #429200
260 public void GetRequestStream ()
262 IPEndPoint ep = new IPEndPoint (IPAddress.Loopback, 8000);
263 string url = "http://" + IPAddress.Loopback.ToString () + ":8000/test/";
265 using (SocketResponder responder = new SocketResponder (ep, new SocketRequestHandler (EchoRequestHandler))) {
268 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
271 req.ReadWriteTimeout = 2000;
273 Stream rs1 = req.GetRequestStream ();
274 Stream rs2 = req.GetRequestStream ();
276 Assert.IsNotNull (rs1, "#1");
277 Assert.AreSame (rs1, rs2, "#2");
285 [Ignore ("This test asserts that our code violates RFC 2616")]
286 public void GetRequestStream_Body_NotAllowed ()
288 string [] methods = new string [] { "GET", "HEAD", "CONNECT",
289 "get", "HeAd", "ConNect" };
291 foreach (string method in methods) {
292 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (
293 "http://localhost:8000");
296 req.GetRequestStream ();
297 Assert.Fail ("#1:" + method);
298 } catch (ProtocolViolationException ex) {
299 Assert.AreEqual (typeof (ProtocolViolationException), ex.GetType (), "#2:" + method);
300 Assert.IsNull (ex.InnerException, "#3:" + method);
301 Assert.IsNotNull (ex.Message, "#4:" + method);
308 [Category("NotWorking")]
310 [Ignore ("This does not timeout any more. That's how MS works when reading small responses")]
311 public void ReadTimeout ()
313 IPEndPoint localEP = new IPEndPoint (IPAddress.Loopback, 8764);
314 string url = "http://" + localEP.ToString () + "/original/";
316 using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (RedirectRequestHandler))) {
319 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
321 req.AllowAutoRedirect = false;
323 req.ReadWriteTimeout = 100;
324 req.KeepAlive = false;
325 Stream rs = req.GetRequestStream ();
327 using (HttpWebResponse resp = (HttpWebResponse) req.GetResponse ()) {
329 Stream s = resp.GetResponseStream ();
332 } catch (WebException ex) {
333 Assert.AreEqual (typeof (WebException), ex.GetType (), "#2");
334 Assert.IsNull (ex.InnerException, "#3");
335 Assert.IsNull (ex.Response, "#4");
336 Assert.AreEqual (WebExceptionStatus.Timeout, ex.Status, "#5");
345 [Category("NotWorking")]
347 [Ignore ("Fails randomly. Need to do more debugging.")]
348 public void AllowAutoRedirect ()
350 IPEndPoint localEP = new IPEndPoint (IPAddress.Loopback, 8764);
351 string url = "http://" + localEP.ToString () + "/original/";
353 // allow autoredirect
354 using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (RedirectRequestHandler))) {
357 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
360 req.ReadWriteTimeout = 2000;
361 req.KeepAlive = false;
362 Stream rs = req.GetRequestStream ();
364 using (HttpWebResponse resp = (HttpWebResponse) req.GetResponse ()) {
365 StreamReader sr = new StreamReader (resp.GetResponseStream (),
367 string body = sr.ReadToEnd ();
369 Assert.AreEqual (resp.StatusCode, HttpStatusCode.OK, "#A1");
370 Assert.AreEqual (resp.ResponseUri.ToString (), "http://" +
371 localEP.ToString () + "/moved/", "#A2");
372 Assert.AreEqual ("GET", resp.Method, "#A3");
373 Assert.AreEqual ("LOOKS OK", body, "#A4");
378 // do not allow autoredirect
379 using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (RedirectRequestHandler))) {
382 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
384 req.AllowAutoRedirect = false;
386 req.ReadWriteTimeout = 1000;
387 req.KeepAlive = false;
388 Stream rs = req.GetRequestStream ();
390 using (HttpWebResponse resp = (HttpWebResponse) req.GetResponse ()) {
391 Assert.AreEqual (resp.StatusCode, HttpStatusCode.Found, "#B1");
392 Assert.AreEqual (url, resp.ResponseUri.ToString (), "#B2");
393 Assert.AreEqual ("POST", resp.Method, "#B3");
400 [Category ("NotWorking")]
401 public void InternalServerError ()
403 IPEndPoint localEP = new IPEndPoint (IPAddress.Loopback, 8764);
404 string url = "http://" + localEP.ToString () + "/original/";
407 using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (InternalErrorHandler))) {
410 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
413 req.ReadWriteTimeout = 2000;
414 req.KeepAlive = false;
415 Stream rs = req.GetRequestStream ();
421 } catch (WebException ex) {
422 Assert.AreEqual (typeof (WebException), ex.GetType (), "#A2");
423 Assert.IsNull (ex.InnerException, "#A3");
424 Assert.IsNotNull (ex.Message, "#A4");
425 Assert.AreEqual (WebExceptionStatus.ProtocolError, ex.Status, "#A5");
427 HttpWebResponse webResponse = ex.Response as HttpWebResponse;
428 Assert.IsNotNull (webResponse, "#A6");
429 Assert.AreEqual ("POST", webResponse.Method, "#A7");
430 webResponse.Close ();
437 using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (InternalErrorHandler))) {
440 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
443 req.ReadWriteTimeout = 2000;
444 req.KeepAlive = false;
449 } catch (WebException ex) {
450 Assert.AreEqual (typeof (WebException), ex.GetType (), "#B2");
451 Assert.IsNull (ex.InnerException, "#B3");
452 Assert.AreEqual (WebExceptionStatus.ProtocolError, ex.Status, "#B4");
454 HttpWebResponse webResponse = ex.Response as HttpWebResponse;
455 Assert.IsNotNull (webResponse, "#B5");
456 Assert.AreEqual ("GET", webResponse.Method, "#B6");
457 webResponse.Close ();
465 [Category ("NotWorking")] // we report a timeout
466 public void NoContentLength ()
468 IPEndPoint localEP = new IPEndPoint (IPAddress.Loopback, 8764);
469 string url = "http://" + localEP.ToString () + "/original/";
472 using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (NoContentLengthHandler))) {
475 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
478 req.ReadWriteTimeout = 2000;
479 req.KeepAlive = false;
480 Stream rs = req.GetRequestStream ();
486 } catch (WebException ex) {
487 Assert.AreEqual (typeof (WebException), ex.GetType (), "#A2");
489 //Assert.IsNotNull (ex.InnerException, "#A3");
490 Assert.AreEqual (WebExceptionStatus.ReceiveFailure, ex.Status, "#A4");
491 Assert.AreEqual (typeof (IOException), ex.InnerException.GetType (), "#A5");
493 // Unable to read data from the transport connection:
494 // A connection attempt failed because the connected party
495 // did not properly respond after a period of time, or
496 // established connection failed because connected host has
498 IOException ioe = (IOException) ex.InnerException;
499 Assert.IsNotNull (ioe.InnerException, "#A6");
500 Assert.IsNotNull (ioe.Message, "#A7");
501 Assert.AreEqual (typeof (SocketException), ioe.InnerException.GetType (), "#A8");
503 // A connection attempt failed because the connected party
504 // did not properly respond after a period of time, or
505 // established connection failed because connected host has
507 SocketException soe = (SocketException) ioe.InnerException;
508 Assert.IsNull (soe.InnerException, "#A9");
509 Assert.IsNotNull (soe.Message, "#A10");
511 HttpWebResponse webResponse = ex.Response as HttpWebResponse;
512 Assert.IsNull (webResponse, "#A11");
514 Assert.IsNull (ex.InnerException, "#A3");
515 Assert.AreEqual (WebExceptionStatus.ProtocolError, ex.Status, "#A4");
517 HttpWebResponse webResponse = ex.Response as HttpWebResponse;
518 Assert.IsNotNull (webResponse, "#A5");
519 Assert.AreEqual ("POST", webResponse.Method, "#A6");
520 webResponse.Close ();
528 using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (NoContentLengthHandler))) {
531 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
534 req.ReadWriteTimeout = 2000;
535 req.KeepAlive = false;
540 } catch (WebException ex) {
541 Assert.AreEqual (typeof (WebException), ex.GetType (), "#B2");
542 Assert.IsNull (ex.InnerException, "#B3");
543 Assert.AreEqual (WebExceptionStatus.ProtocolError, ex.Status, "#B4");
545 HttpWebResponse webResponse = ex.Response as HttpWebResponse;
546 Assert.IsNotNull (webResponse, "#B5");
547 Assert.AreEqual ("GET", webResponse.Method, "#B6");
548 webResponse.Close ();
558 [Category ("NotWorking")]
560 public void Stream_CanTimeout ()
562 IPEndPoint localEP = new IPEndPoint (IPAddress.Loopback, 8764);
563 string url = "http://" + localEP.ToString () + "/original/";
565 // allow autoredirect
566 using (SocketResponder responder = new SocketResponder (localEP, new SocketRequestHandler (RedirectRequestHandler))) {
569 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
572 req.ReadWriteTimeout = 2000;
573 req.KeepAlive = false;
574 Stream rs = req.GetRequestStream ();
575 Assert.IsTrue (rs.CanTimeout, "#1");
577 using (HttpWebResponse resp = (HttpWebResponse) req.GetResponse ()) {
578 Stream os = resp.GetResponseStream ();
579 Assert.IsTrue (os.CanTimeout, "#2");
587 [Test] // bug #353495
588 [Category ("NotWorking")]
589 public void LastModifiedKind ()
591 const string reqURL = "http://coffeefaq.com/site/node/25";
592 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (reqURL);
593 HttpWebResponse resp = (HttpWebResponse) req.GetResponse ();
594 DateTime lastMod = resp.LastModified;
595 string rawLastMod = resp.Headers ["Last-Modified"];
597 //Assert.AreEqual ("Tue, 15 Jan 2008 08:59:59 GMT", rawLastMod, "#1");
599 Assert.AreEqual (DateTimeKind.Local, lastMod.Kind, "#2");
601 req = (HttpWebRequest) WebRequest.Create (reqURL);
602 req.IfModifiedSince = lastMod;
604 resp = (HttpWebResponse) req.GetResponse ();
606 Assert.Fail ("Should result in 304");
607 } catch (WebException ex) {
608 Assert.AreEqual (WebExceptionStatus.ProtocolError, ex.Status, "#3");
609 Assert.AreEqual (((HttpWebResponse) ex.Response).StatusCode, HttpStatusCode.NotModified, "#4");
613 static byte [] EchoRequestHandler (Socket socket)
615 MemoryStream ms = new MemoryStream ();
616 byte [] buffer = new byte [4096];
617 int bytesReceived = socket.Receive (buffer);
618 while (bytesReceived > 0) {
619 ms.Write (buffer, 0, bytesReceived);
620 if (socket.Available > 0) {
621 bytesReceived = socket.Receive (buffer);
628 StreamReader sr = new StreamReader (ms, Encoding.UTF8);
629 string request = sr.ReadToEnd ();
631 StringWriter sw = new StringWriter ();
632 sw.WriteLine ("HTTP/1.1 200 OK");
633 sw.WriteLine ("Content-Type: text/xml");
634 sw.WriteLine ("Content-Length: " + request.Length.ToString (CultureInfo.InvariantCulture));
639 return Encoding.UTF8.GetBytes (sw.ToString ());
642 static byte [] RedirectRequestHandler (Socket socket)
644 MemoryStream ms = new MemoryStream ();
645 byte [] buffer = new byte [4096];
646 int bytesReceived = socket.Receive (buffer);
647 while (bytesReceived > 0) {
648 ms.Write (buffer, 0, bytesReceived);
649 if (socket.Available > 0) {
650 bytesReceived = socket.Receive (buffer);
657 string statusLine = null;
658 using (StreamReader sr = new StreamReader (ms, Encoding.UTF8)) {
659 statusLine = sr.ReadLine ();
662 StringWriter sw = new StringWriter ();
663 if (statusLine.StartsWith ("POST /original/")) {
664 sw.WriteLine ("HTTP/1.0 302 Found");
665 sw.WriteLine ("Location: " + "http://" + IPAddress.Loopback.ToString () + ":8764/moved/");
668 } else if (statusLine.StartsWith ("GET /moved/")) {
669 sw.WriteLine ("HTTP/1.0 200 OK");
670 sw.WriteLine ("Content-Type: text/plain");
671 sw.WriteLine ("Content-Length: 8");
673 sw.Write ("LOOKS OK");
676 sw.WriteLine ("HTTP/1.0 500 Too Lazy");
681 return Encoding.UTF8.GetBytes (sw.ToString ());
684 static byte [] InternalErrorHandler (Socket socket)
686 StringWriter sw = new StringWriter ();
687 sw.WriteLine ("HTTP/1.1 500 Too Lazy");
688 sw.WriteLine ("Content-Length: 0");
692 return Encoding.UTF8.GetBytes (sw.ToString ());
695 static byte [] NoContentLengthHandler (Socket socket)
697 StringWriter sw = new StringWriter ();
698 sw.WriteLine ("HTTP/1.1 500 Too Lazy");
702 return Encoding.UTF8.GetBytes (sw.ToString ());
706 public void NtlmAuthentication ()
708 NtlmServer server = new NtlmServer ();
711 string url = String.Format ("http://{0}:{1}/nothing.html", server.IPAddress, server.Port);
712 HttpWebRequest request = (HttpWebRequest) WebRequest.Create (url);
713 request.Timeout = 5000;
714 request.Credentials = new NetworkCredential ("user", "password", "domain");
715 HttpWebResponse resp = (HttpWebResponse) request.GetResponse ();
717 using (StreamReader reader = new StreamReader (resp.GetResponseStream ())) {
718 res = reader.ReadToEnd ();
722 Assert.AreEqual ("OK", res);
725 class NtlmServer : HttpServer {
726 public string Where = "";
727 protected override void Run ()
729 Where = "before accept";
730 Socket client = sock.Accept ();
731 NetworkStream ns = new NetworkStream (client, false);
732 StreamReader reader = new StreamReader (ns, Encoding.ASCII);
734 Where = "first read";
735 while ((line = reader.ReadLine ()) != null) {
736 if (line.Trim () == String.Empty) {
740 Where = "first write";
741 StreamWriter writer = new StreamWriter (ns, Encoding.ASCII);
742 writer.Write ( "HTTP/1.1 401 Unauthorized\r\n" +
743 "WWW-Authenticate: NTLM\r\n" +
744 "Content-Length: 5\r\n\r\nWRONG");
747 Where = "second read";
748 while ((line = reader.ReadLine ()) != null) {
749 if (line.Trim () == String.Empty) {
753 Where = "second write";
754 writer.Write ( "HTTP/1.1 401 Unauthorized\r\n" +
755 "WWW-Authenticate: NTLM TlRMTVNTUAACAAAAAAAAADgAAAABggAC8GDhqIONH3sAAAAAAAAAAAAAAAA4AAAABQLODgAAAA8=\r\n" +
756 "Content-Length: 5\r\n\r\nWRONG");
759 Where = "third read";
760 while ((line = reader.ReadLine ()) != null) {
761 if (line.Trim () == String.Empty) {
765 Where = "third write";
766 writer.Write ( "HTTP/1.1 200 OK\r\n" +
767 "Keep-Alive: true\r\n" +
768 "Content-Length: 2\r\n\r\nOK");
777 class BadChunkedServer : HttpServer {
778 protected override void Run ()
780 Socket client = sock.Accept ();
781 NetworkStream ns = new NetworkStream (client, true);
782 StreamWriter writer = new StreamWriter (ns, Encoding.ASCII);
783 writer.Write ( "HTTP/1.1 200 OK\r\n" +
784 "Transfer-Encoding: chunked\r\n" +
785 "Connection: close\r\n" +
786 "Content-Type: text/plain; charset=UTF-8\r\n\r\n");
788 // This body lacks a 'last-chunk' (see RFC 2616)
789 writer.Write ("10\r\n1234567890123456\r\n");
791 client.Shutdown (SocketShutdown.Send);
797 class AcceptAllPolicy : ICertificatePolicy {
798 public bool CheckValidationResult (ServicePoint sp, X509Certificate certificate, WebRequest request, int error)
804 abstract class HttpServer
806 protected Socket sock;
807 protected Exception error;
808 protected ManualResetEvent evt;
812 sock = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
813 sock.Bind (new IPEndPoint (IPAddress.Loopback, 0));
819 evt = new ManualResetEvent (false);
820 Thread th = new Thread (new ThreadStart (Run));
830 public IPAddress IPAddress {
831 get { return ((IPEndPoint) sock.LocalEndPoint).Address; }
835 get { return ((IPEndPoint) sock.LocalEndPoint).Port; }
838 public Exception Error {
839 get { return error; }
842 protected abstract void Run ();
846 class SslHttpServer : HttpServer {
847 X509Certificate _certificate;
849 protected override void Run ()
852 Socket client = sock.Accept ();
853 NetworkStream ns = new NetworkStream (client, true);
854 SslServerStream s = new SslServerStream (ns, Certificate, false, false);
855 s.PrivateKeyCertSelectionDelegate += new PrivateKeySelectionCallback (GetPrivateKey);
857 StreamReader reader = new StreamReader (s);
858 StreamWriter writer = new StreamWriter (s, Encoding.ASCII);
861 string hello = "<html><body><h1>Hello World!</h1></body></html>";
862 string answer = "HTTP/1.0 200\r\n" +
863 "Connection: close\r\n" +
864 "Content-Type: text/html\r\n" +
865 "Content-Encoding: " + Encoding.ASCII.WebName + "\r\n" +
866 "Content-Length: " + hello.Length + "\r\n" +
871 line = reader.ReadLine ();
872 } while (line != "" && line != null && line.Length > 0);
874 // Now the content. We know it's 100 bytes.
875 // This makes BeginRead in sslclientstream block.
876 char [] cs = new char [100];
877 reader.Read (cs, 0, 100);
879 writer.Write (answer);
881 evt.WaitOne (50000, false);
882 } catch (Exception e) {
887 X509Certificate Certificate {
889 if (_certificate == null)
890 _certificate = new X509Certificate (CertData.Certificate);
896 AsymmetricAlgorithm GetPrivateKey (X509Certificate certificate, string targetHost)
898 PrivateKey key = new PrivateKey (CertData.PrivateKey, null);
904 public readonly static byte [] Certificate = {
905 48, 130, 1, 191, 48, 130, 1, 40, 160, 3, 2, 1, 2, 2, 16, 36,
906 14, 97, 190, 146, 132, 208, 71, 175, 6, 87, 168, 185, 175, 55, 43, 48,
907 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 4, 5, 0, 48, 18,
908 49, 16, 48, 14, 6, 3, 85, 4, 3, 19, 7, 103, 111, 110, 122, 97,
909 108, 111, 48, 30, 23, 13, 48, 53, 48, 54, 50, 50, 49, 57, 51, 48,
910 52, 54, 90, 23, 13, 51, 57, 49, 50, 51, 49, 50, 51, 53, 57, 53,
911 57, 90, 48, 18, 49, 16, 48, 14, 6, 3, 85, 4, 3, 19, 7, 103,
912 111, 110, 122, 97, 108, 111, 48, 129, 158, 48, 13, 6, 9, 42, 134, 72,
913 134, 247, 13, 1, 1, 1, 5, 0, 3, 129, 140, 0, 48, 129, 136, 2,
914 129, 129, 0, 138, 9, 38, 25, 166, 252, 59, 26, 39, 184, 128, 216, 38,
915 73, 41, 86, 30, 228, 160, 205, 41, 135, 115, 223, 44, 62, 42, 198, 178,
916 190, 81, 11, 25, 21, 216, 49, 179, 130, 246, 52, 97, 175, 212, 94, 157,
917 231, 162, 66, 161, 103, 63, 204, 83, 141, 172, 119, 97, 225, 206, 98, 101,
918 210, 106, 2, 206, 81, 90, 173, 47, 41, 199, 209, 241, 177, 177, 96, 207,
919 254, 220, 190, 66, 180, 153, 0, 209, 14, 178, 69, 194, 3, 37, 116, 239,
920 49, 23, 185, 245, 255, 126, 35, 85, 246, 56, 244, 107, 117, 24, 14, 57,
921 9, 111, 147, 189, 220, 142, 57, 104, 153, 193, 205, 19, 14, 22, 157, 16,
922 24, 80, 201, 2, 2, 0, 17, 163, 23, 48, 21, 48, 19, 6, 3, 85,
923 29, 37, 4, 12, 48, 10, 6, 8, 43, 6, 1, 5, 5, 7, 3, 1,
924 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 4, 5, 0, 3,
925 129, 129, 0, 64, 49, 57, 253, 218, 198, 229, 51, 189, 12, 154, 225, 183,
926 160, 147, 90, 113, 172, 69, 122, 28, 77, 97, 215, 231, 194, 150, 29, 196,
927 65, 95, 218, 99, 142, 111, 79, 205, 109, 76, 32, 92, 220, 76, 88, 53,
928 237, 80, 11, 85, 44, 91, 21, 210, 12, 34, 223, 234, 18, 187, 136, 62,
929 26, 240, 103, 180, 12, 226, 221, 250, 247, 129, 51, 23, 129, 165, 56, 67,
930 43, 83, 244, 110, 207, 24, 253, 195, 16, 46, 80, 113, 80, 18, 2, 254,
931 120, 147, 151, 164, 23, 210, 230, 100, 19, 197, 179, 28, 194, 48, 106, 159,
932 155, 144, 37, 82, 44, 160, 40, 52, 146, 174, 77, 188, 160, 230, 75, 172,
936 public readonly static byte [] PrivateKey = {
937 30, 241, 181, 176, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,
938 0, 0, 0, 0, 84, 2, 0, 0, 7, 2, 0, 0, 0, 36, 0, 0,
939 82, 83, 65, 50, 0, 4, 0, 0, 17, 0, 0, 0, 201, 80, 24, 16,
940 157, 22, 14, 19, 205, 193, 153, 104, 57, 142, 220, 189, 147, 111, 9, 57,
941 14, 24, 117, 107, 244, 56, 246, 85, 35, 126, 255, 245, 185, 23, 49, 239,
942 116, 37, 3, 194, 69, 178, 14, 209, 0, 153, 180, 66, 190, 220, 254, 207,
943 96, 177, 177, 241, 209, 199, 41, 47, 173, 90, 81, 206, 2, 106, 210, 101,
944 98, 206, 225, 97, 119, 172, 141, 83, 204, 63, 103, 161, 66, 162, 231, 157,
945 94, 212, 175, 97, 52, 246, 130, 179, 49, 216, 21, 25, 11, 81, 190, 178,
946 198, 42, 62, 44, 223, 115, 135, 41, 205, 160, 228, 30, 86, 41, 73, 38,
947 216, 128, 184, 39, 26, 59, 252, 166, 25, 38, 9, 138, 175, 88, 190, 223,
948 27, 24, 224, 123, 190, 69, 164, 234, 129, 59, 108, 229, 248, 62, 187, 15,
949 235, 147, 162, 83, 47, 123, 170, 190, 224, 31, 215, 110, 143, 31, 227, 216,
950 85, 88, 154, 83, 207, 229, 41, 28, 237, 116, 181, 17, 37, 141, 224, 185,
951 164, 144, 141, 233, 164, 138, 177, 241, 115, 181, 230, 150, 7, 92, 139, 141,
952 113, 95, 57, 191, 211, 165, 217, 250, 197, 68, 164, 184, 168, 43, 48, 65,
953 177, 237, 173, 144, 148, 221, 62, 189, 147, 63, 216, 188, 206, 103, 226, 171,
954 32, 20, 230, 116, 144, 192, 1, 39, 202, 87, 74, 250, 6, 142, 188, 23,
955 45, 4, 112, 191, 253, 67, 69, 70, 128, 143, 44, 234, 41, 96, 195, 82,
956 202, 35, 158, 149, 240, 151, 23, 25, 166, 179, 85, 144, 58, 120, 149, 229,
957 205, 34, 8, 110, 86, 119, 130, 210, 37, 173, 65, 71, 169, 67, 8, 51,
958 20, 96, 51, 155, 3, 39, 85, 187, 40, 193, 57, 19, 99, 78, 173, 28,
959 129, 154, 108, 175, 8, 138, 237, 71, 27, 148, 129, 35, 47, 57, 101, 237,
960 168, 178, 227, 221, 212, 63, 124, 254, 253, 215, 183, 159, 49, 103, 74, 49,
961 67, 160, 171, 72, 194, 215, 108, 251, 178, 18, 184, 100, 211, 105, 21, 186,
962 39, 66, 218, 154, 72, 222, 90, 237, 179, 251, 51, 224, 212, 56, 251, 6,
963 209, 151, 198, 176, 89, 110, 35, 141, 248, 237, 223, 68, 135, 206, 207, 169,
964 254, 219, 243, 130, 71, 11, 94, 113, 233, 92, 63, 156, 169, 72, 215, 110,
965 95, 94, 191, 50, 59, 89, 187, 59, 183, 99, 161, 146, 233, 245, 219, 80,
966 87, 113, 251, 50, 144, 195, 158, 46, 189, 232, 119, 91, 75, 22, 6, 176,
967 39, 206, 25, 196, 213, 195, 219, 24, 28, 103, 104, 36, 137, 128, 4, 119,
968 163, 40, 126, 87, 18, 86, 128, 243, 213, 101, 2, 237, 78, 64, 160, 55,
969 199, 93, 90, 126, 175, 199, 55, 89, 234, 190, 5, 16, 196, 88, 28, 208,
970 28, 92, 32, 115, 204, 9, 202, 101, 15, 123, 43, 75, 90, 144, 95, 179,
971 102, 249, 57, 150, 204, 99, 147, 203, 16, 63, 81, 244, 226, 237, 82, 204,
972 20, 200, 140, 65, 83, 217, 161, 23, 123, 37, 115, 12, 100, 73, 70, 190,
973 32, 235, 174, 140, 148, 157, 47, 238, 40, 208, 228, 80, 54, 187, 156, 252,
974 253, 230, 231, 156, 138, 125, 96, 79, 3, 27, 143, 55, 146, 169, 165, 61,
975 238, 60, 227, 77, 217, 93, 117, 122, 111, 46, 173, 113,