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 Assertion.AssertEquals ("req Header 1", "User-Agent", req.Headers.GetKey (0));
72 Assertion.AssertEquals ("req Header 2", "MonoClient v1.0", req.Headers.Get (0));
74 HttpWebResponse res = (HttpWebResponse) req.GetResponse ();
75 Assertion.AssertEquals ("res:HttpStatusCode: ", "OK", res.StatusCode.ToString ());
76 Assertion.AssertEquals ("res:HttpStatusDescription: ", "OK", res.StatusDescription);
78 Assertion.AssertEquals ("res Header 1", "text/html", res.Headers.Get ("Content-Type"));
79 Assertion.AssertNotNull ("Last Modified: ", res.LastModified);
81 Assertion.AssertEquals ("res:", 0, res.Cookies.Count);
87 public void AddRange ()
89 HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://www.google.com");
91 req.AddRange (50, 90);
92 req.AddRange ("bytes", 100);
93 req.AddRange ("bytes", 100, 120);
94 Assertion.AssertEquals ("#1", "bytes=10-,50-90,100-,100-120", req.Headers ["Range"]);
96 req.AddRange ("bits", 2000);
97 Assertion.Fail ("#2");
98 } catch (InvalidOperationException) {}
102 [Category("InetAccess")]
103 public void Cookies1 ()
105 // The purpose of this test is to ensure that the cookies we get from a request
106 // are stored in both, the CookieCollection in HttpWebResponse and the CookieContainer
107 // in HttpWebRequest.
108 // If this URL stops sending *one* and only one cookie, replace it.
109 string url = "http://www.elmundo.es";
110 CookieContainer cookies = new CookieContainer ();
111 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (url);
112 req.KeepAlive = false;
113 req.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv; 1.7.6) Gecko/20050317 Firefox/1.0.2";
114 req.CookieContainer = cookies;
115 Assertion.AssertEquals ("#01", 0, cookies.Count);
116 using (HttpWebResponse res = (HttpWebResponse) req.GetResponse()) {
117 CookieCollection coll = req.CookieContainer.GetCookies (new Uri (url));
118 Assertion.AssertEquals ("#02", 1, coll.Count);
119 Assertion.AssertEquals ("#03", 1, res.Cookies.Count);
120 Cookie one = coll [0];
121 Cookie two = res.Cookies [0];
122 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",
260 [Ignore ("This test asserts that our code violates RFC 2616")]
261 public void GetRequestStream_Body_NotAllowed ()
263 string [] methods = new string [] { "GET", "HEAD", "CONNECT",
264 "get", "HeAd", "ConNect" };
266 foreach (string method in methods) {
267 HttpWebRequest req = (HttpWebRequest) WebRequest.Create (
268 "http://localhost:8000");
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);
281 private static byte [] EchoRequestHandler (Socket socket)
283 MemoryStream ms = new MemoryStream ();
284 byte [] buffer = new byte [4096];
285 int bytesReceived = socket.Receive (buffer);
286 while (bytesReceived > 0) {
287 ms.Write (buffer, 0, bytesReceived);
288 if (socket.Available > 0) {
289 bytesReceived = socket.Receive (buffer);
296 StreamReader sr = new StreamReader (ms, Encoding.UTF8);
297 string request = sr.ReadToEnd ();
299 MemoryStream outputStream = new MemoryStream ();
300 StringWriter sw = new StringWriter ();
301 sw.WriteLine ("HTTP/1.1 200 OK");
302 sw.WriteLine ("Content-Type: text/xml");
303 sw.WriteLine ("Content-Length: " + request.Length.ToString (CultureInfo.InvariantCulture));
308 return Encoding.UTF8.GetBytes (sw.ToString ());
311 class BadChunkedServer : HttpServer {
312 protected override void Run ()
314 Socket client = sock.Accept ();
315 NetworkStream ns = new NetworkStream (client, true);
316 StreamWriter writer = new StreamWriter (ns, Encoding.ASCII);
317 writer.Write ( "HTTP/1.1 200 OK\r\n" +
318 "Transfer-Encoding: chunked\r\n" +
319 "Connection: close\r\n" +
320 "Content-Type: text/plain; charset=UTF-8\r\n\r\n");
322 // This body lacks a 'last-chunk' (see RFC 2616)
323 writer.Write ("10\r\n1234567890123456\r\n");
325 client.Shutdown (SocketShutdown.Send);
331 class AcceptAllPolicy : ICertificatePolicy {
332 public bool CheckValidationResult (ServicePoint sp, X509Certificate certificate, WebRequest request, int error)
338 abstract class HttpServer
340 protected Socket sock;
341 protected Exception error;
342 protected ManualResetEvent evt;
346 sock = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
347 sock.Bind (new IPEndPoint (IPAddress.Loopback, 0));
353 evt = new ManualResetEvent (false);
354 Thread th = new Thread (new ThreadStart (Run));
364 public IPAddress IPAddress {
365 get { return ((IPEndPoint) sock.LocalEndPoint).Address; }
369 get { return ((IPEndPoint) sock.LocalEndPoint).Port; }
372 public Exception Error {
373 get { return error; }
376 protected abstract void Run ();
380 class SslHttpServer : HttpServer {
381 X509Certificate _certificate;
383 protected override void Run ()
386 Socket client = sock.Accept ();
387 NetworkStream ns = new NetworkStream (client, true);
388 SslServerStream s = new SslServerStream (ns, Certificate, false, false);
389 s.PrivateKeyCertSelectionDelegate += new PrivateKeySelectionCallback (GetPrivateKey);
391 StreamReader reader = new StreamReader (s);
392 StreamWriter writer = new StreamWriter (s, Encoding.ASCII);
395 string hello = "<html><body><h1>Hello World!</h1></body></html>";
396 string answer = "HTTP/1.0 200\r\n" +
397 "Connection: close\r\n" +
398 "Content-Type: text/html\r\n" +
399 "Content-Encoding: " + Encoding.ASCII.WebName + "\r\n" +
400 "Content-Length: " + hello.Length + "\r\n" +
405 line = reader.ReadLine ();
406 } while (line != "" && line != null && line.Length > 0);
408 // Now the content. We know it's 100 bytes.
409 // This makes BeginRead in sslclientstream block.
410 char [] cs = new char [100];
411 reader.Read (cs, 0, 100);
413 writer.Write (answer);
415 evt.WaitOne (50000, false);
416 } catch (Exception e) {
421 X509Certificate Certificate {
423 if (_certificate == null)
424 _certificate = new X509Certificate (CertData.Certificate);
430 AsymmetricAlgorithm GetPrivateKey (X509Certificate certificate, string targetHost)
432 PrivateKey key = new PrivateKey (CertData.PrivateKey, null);
438 public readonly static byte [] Certificate = {
439 48, 130, 1, 191, 48, 130, 1, 40, 160, 3, 2, 1, 2, 2, 16, 36,
440 14, 97, 190, 146, 132, 208, 71, 175, 6, 87, 168, 185, 175, 55, 43, 48,
441 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 4, 5, 0, 48, 18,
442 49, 16, 48, 14, 6, 3, 85, 4, 3, 19, 7, 103, 111, 110, 122, 97,
443 108, 111, 48, 30, 23, 13, 48, 53, 48, 54, 50, 50, 49, 57, 51, 48,
444 52, 54, 90, 23, 13, 51, 57, 49, 50, 51, 49, 50, 51, 53, 57, 53,
445 57, 90, 48, 18, 49, 16, 48, 14, 6, 3, 85, 4, 3, 19, 7, 103,
446 111, 110, 122, 97, 108, 111, 48, 129, 158, 48, 13, 6, 9, 42, 134, 72,
447 134, 247, 13, 1, 1, 1, 5, 0, 3, 129, 140, 0, 48, 129, 136, 2,
448 129, 129, 0, 138, 9, 38, 25, 166, 252, 59, 26, 39, 184, 128, 216, 38,
449 73, 41, 86, 30, 228, 160, 205, 41, 135, 115, 223, 44, 62, 42, 198, 178,
450 190, 81, 11, 25, 21, 216, 49, 179, 130, 246, 52, 97, 175, 212, 94, 157,
451 231, 162, 66, 161, 103, 63, 204, 83, 141, 172, 119, 97, 225, 206, 98, 101,
452 210, 106, 2, 206, 81, 90, 173, 47, 41, 199, 209, 241, 177, 177, 96, 207,
453 254, 220, 190, 66, 180, 153, 0, 209, 14, 178, 69, 194, 3, 37, 116, 239,
454 49, 23, 185, 245, 255, 126, 35, 85, 246, 56, 244, 107, 117, 24, 14, 57,
455 9, 111, 147, 189, 220, 142, 57, 104, 153, 193, 205, 19, 14, 22, 157, 16,
456 24, 80, 201, 2, 2, 0, 17, 163, 23, 48, 21, 48, 19, 6, 3, 85,
457 29, 37, 4, 12, 48, 10, 6, 8, 43, 6, 1, 5, 5, 7, 3, 1,
458 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 4, 5, 0, 3,
459 129, 129, 0, 64, 49, 57, 253, 218, 198, 229, 51, 189, 12, 154, 225, 183,
460 160, 147, 90, 113, 172, 69, 122, 28, 77, 97, 215, 231, 194, 150, 29, 196,
461 65, 95, 218, 99, 142, 111, 79, 205, 109, 76, 32, 92, 220, 76, 88, 53,
462 237, 80, 11, 85, 44, 91, 21, 210, 12, 34, 223, 234, 18, 187, 136, 62,
463 26, 240, 103, 180, 12, 226, 221, 250, 247, 129, 51, 23, 129, 165, 56, 67,
464 43, 83, 244, 110, 207, 24, 253, 195, 16, 46, 80, 113, 80, 18, 2, 254,
465 120, 147, 151, 164, 23, 210, 230, 100, 19, 197, 179, 28, 194, 48, 106, 159,
466 155, 144, 37, 82, 44, 160, 40, 52, 146, 174, 77, 188, 160, 230, 75, 172,
470 public readonly static byte [] PrivateKey = {
471 30, 241, 181, 176, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,
472 0, 0, 0, 0, 84, 2, 0, 0, 7, 2, 0, 0, 0, 36, 0, 0,
473 82, 83, 65, 50, 0, 4, 0, 0, 17, 0, 0, 0, 201, 80, 24, 16,
474 157, 22, 14, 19, 205, 193, 153, 104, 57, 142, 220, 189, 147, 111, 9, 57,
475 14, 24, 117, 107, 244, 56, 246, 85, 35, 126, 255, 245, 185, 23, 49, 239,
476 116, 37, 3, 194, 69, 178, 14, 209, 0, 153, 180, 66, 190, 220, 254, 207,
477 96, 177, 177, 241, 209, 199, 41, 47, 173, 90, 81, 206, 2, 106, 210, 101,
478 98, 206, 225, 97, 119, 172, 141, 83, 204, 63, 103, 161, 66, 162, 231, 157,
479 94, 212, 175, 97, 52, 246, 130, 179, 49, 216, 21, 25, 11, 81, 190, 178,
480 198, 42, 62, 44, 223, 115, 135, 41, 205, 160, 228, 30, 86, 41, 73, 38,
481 216, 128, 184, 39, 26, 59, 252, 166, 25, 38, 9, 138, 175, 88, 190, 223,
482 27, 24, 224, 123, 190, 69, 164, 234, 129, 59, 108, 229, 248, 62, 187, 15,
483 235, 147, 162, 83, 47, 123, 170, 190, 224, 31, 215, 110, 143, 31, 227, 216,
484 85, 88, 154, 83, 207, 229, 41, 28, 237, 116, 181, 17, 37, 141, 224, 185,
485 164, 144, 141, 233, 164, 138, 177, 241, 115, 181, 230, 150, 7, 92, 139, 141,
486 113, 95, 57, 191, 211, 165, 217, 250, 197, 68, 164, 184, 168, 43, 48, 65,
487 177, 237, 173, 144, 148, 221, 62, 189, 147, 63, 216, 188, 206, 103, 226, 171,
488 32, 20, 230, 116, 144, 192, 1, 39, 202, 87, 74, 250, 6, 142, 188, 23,
489 45, 4, 112, 191, 253, 67, 69, 70, 128, 143, 44, 234, 41, 96, 195, 82,
490 202, 35, 158, 149, 240, 151, 23, 25, 166, 179, 85, 144, 58, 120, 149, 229,
491 205, 34, 8, 110, 86, 119, 130, 210, 37, 173, 65, 71, 169, 67, 8, 51,
492 20, 96, 51, 155, 3, 39, 85, 187, 40, 193, 57, 19, 99, 78, 173, 28,
493 129, 154, 108, 175, 8, 138, 237, 71, 27, 148, 129, 35, 47, 57, 101, 237,
494 168, 178, 227, 221, 212, 63, 124, 254, 253, 215, 183, 159, 49, 103, 74, 49,
495 67, 160, 171, 72, 194, 215, 108, 251, 178, 18, 184, 100, 211, 105, 21, 186,
496 39, 66, 218, 154, 72, 222, 90, 237, 179, 251, 51, 224, 212, 56, 251, 6,
497 209, 151, 198, 176, 89, 110, 35, 141, 248, 237, 223, 68, 135, 206, 207, 169,
498 254, 219, 243, 130, 71, 11, 94, 113, 233, 92, 63, 156, 169, 72, 215, 110,
499 95, 94, 191, 50, 59, 89, 187, 59, 183, 99, 161, 146, 233, 245, 219, 80,
500 87, 113, 251, 50, 144, 195, 158, 46, 189, 232, 119, 91, 75, 22, 6, 176,
501 39, 206, 25, 196, 213, 195, 219, 24, 28, 103, 104, 36, 137, 128, 4, 119,
502 163, 40, 126, 87, 18, 86, 128, 243, 213, 101, 2, 237, 78, 64, 160, 55,
503 199, 93, 90, 126, 175, 199, 55, 89, 234, 190, 5, 16, 196, 88, 28, 208,
504 28, 92, 32, 115, 204, 9, 202, 101, 15, 123, 43, 75, 90, 144, 95, 179,
505 102, 249, 57, 150, 204, 99, 147, 203, 16, 63, 81, 244, 226, 237, 82, 204,
506 20, 200, 140, 65, 83, 217, 161, 23, 123, 37, 115, 12, 100, 73, 70, 190,
507 32, 235, 174, 140, 148, 157, 47, 238, 40, 208, 228, 80, 54, 187, 156, 252,
508 253, 230, 231, 156, 138, 125, 96, 79, 3, 27, 143, 55, 146, 169, 165, 61,
509 238, 60, 227, 77, 217, 93, 117, 122, 111, 46, 173, 113,