[HttpWebRequest] Support 4.0 Host property.
authorGonzalo Paniagua Javier <gonzalo.mono@gmail.com>
Mon, 17 Jan 2011 06:04:37 +0000 (01:04 -0500)
committerGonzalo Paniagua Javier <gonzalo.mono@gmail.com>
Tue, 18 Jan 2011 17:52:58 +0000 (12:52 -0500)
mcs/class/System/System.Net/HttpWebRequest.cs
mcs/class/System/Test/System.Net/HttpWebRequestTest.cs

index 0aa0f03ccf9f22ec83cd3656ea4918817670dc83..418f715824b9d26a0423da51867b5a203ea9f1c6 100644 (file)
@@ -109,6 +109,7 @@ namespace System.Net
                        Response
                }
                NtlmAuthState ntlm_auth_state;
+               string host;
 
                // Constructors
                static HttpWebRequest ()
@@ -162,6 +163,7 @@ namespace System.Net
                        sendChunked = info.GetBoolean ("sendChunked");
                        timeout = info.GetInt32 ("timeout");
                        redirects = info.GetInt32 ("redirects");
+                       host = info.GetString ("host");
                }
                
                // Properties
@@ -352,7 +354,55 @@ namespace System.Net
                                webHeaders = newHeaders;
                        }
                }
-               
+#if NET_4_0
+               public
+#else
+               internal
+#endif
+               string Host {
+                       get {
+                               if (host == null)
+                                       return actualUri.Authority;
+                               return host;
+                       }
+                       set {
+                               if (value == null)
+                                       throw new ArgumentNullException ("value");
+
+                               if (!CheckValidHost (value))
+                                       throw new ArgumentException ("Invalid host: " + value);
+
+                               host = value;
+                       }
+               }
+
+               static char [] colon = { ':' };
+               static bool CheckValidHost (string val)
+               {
+                       if (val == null)
+                               throw new ArgumentNullException ("value");
+
+                       if (val.Length == 0)
+                               return false;
+
+                       if (val [0] == '.')
+                               return false;
+
+                       string [] parts = val.Split ('.');
+                       int l = parts.Length;
+                       string [] last = parts [l - 1].Split (colon, 2);
+                       if (last.Length == 2) {
+                               parts [l - 1] = last [0];
+                               ushort port;
+                               if (!UInt16.TryParse (parts [1], out port))
+                                       return false;
+                       }
+
+                       // MS does not enforce a max. 255 length
+                       // MS does not complain about a leading dash or all numbers...
+                       return true;
+               }
+
                public DateTime IfModifiedSince {
                        get { 
                                string str = webHeaders ["If-Modified-Since"];
@@ -879,6 +929,7 @@ namespace System.Net
                        info.AddValue ("sendChunked", sendChunked);
                        info.AddValue ("timeout", timeout);
                        info.AddValue ("redirects", redirects);
+                       info.AddValue ("host", host);
                }
                
                void CheckRequestStarted () 
@@ -949,8 +1000,7 @@ namespace System.Net
                                                                        WebExceptionStatus.ProtocolError);
                        }
 
-                       hostChanged = (actualUri.Scheme != prev.Scheme || actualUri.Host != prev.Host ||
-                                       actualUri.Port != prev.Port);
+                       hostChanged = (actualUri.Scheme != prev.Scheme || Host != prev.Authority);
                        return true;
                }
 
@@ -996,7 +1046,7 @@ namespace System.Net
                                webHeaders.RemoveAndAdd (connectionHeader, "close");
                        }
 
-                       webHeaders.SetInternal ("Host", actualUri.Authority);
+                       webHeaders.SetInternal ("Host", Host);
                        if (cookieContainer != null) {
                                string cookieHeader = cookieContainer.GetCookieHeader (actualUri);
                                if (cookieHeader != "")
@@ -1062,15 +1112,10 @@ namespace System.Net
                        string query;
                        if (!ProxyQuery) {
                                query = actualUri.PathAndQuery;
-                       } else if (actualUri.IsDefaultPort) {
+                       } else {
                                query = String.Format ("{0}://{1}{2}",  actualUri.Scheme,
-                                                                       actualUri.Host,
+                                                                       Host,
                                                                        actualUri.PathAndQuery);
-                       } else {
-                               query = String.Format ("{0}://{1}:{2}{3}", actualUri.Scheme,
-                                                                          actualUri.Host,
-                                                                          actualUri.Port,
-                                                                          actualUri.PathAndQuery);
                        }
                        
                        if (servicePoint.ProtocolVersion != null && servicePoint.ProtocolVersion < version) {
index fec6418f9d24535a8ec97fb8231050d21e8a5299..050ecc5047f2fe3bfd673cc3bb61f1f11c31e40c 100644 (file)
@@ -2312,6 +2312,79 @@ namespace MonoTests.System.Net
                        }
                }
 
+#if NET_4_0
+               [Test]
+               [ExpectedException (typeof (ArgumentNullException))]
+               public void NullHost ()
+               {
+                       HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://go-mono.com");
+                       req.Host = null;
+               }
+
+               [Test]
+               public void NoHost ()
+               {
+                       HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://go-mono.com");
+                       Assert.AreEqual (req.Host, "go-mono.com");
+               }
+
+               [Test]
+               [ExpectedException (typeof (ArgumentException))]
+               public void EmptyHost ()
+               {
+                       HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://go-mono.com");
+                       req.Host = "";
+               }
+
+               [Test]
+               public void HostAndPort ()
+               {
+                       HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://go-mono.com:80");
+                       Assert.AreEqual ("go-mono.com", req.Host, "#01");
+                       req = (HttpWebRequest) WebRequest.Create ("http://go-mono.com:9000");
+                       Assert.AreEqual ("go-mono.com:9000", req.Host, "#02");
+               }
+
+               [Test]
+               public void PortRange ()
+               {
+                       for (int i = 0; i < 65536; i++) {
+                               if (i == 80)
+                                       continue;
+                               string s = i.ToString ();
+                               HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://go-mono.com:" + s);
+                               Assert.AreEqual ("go-mono.com:" + s, req.Host, "#" + s);
+                       }
+               }
+
+               [Test]
+               [ExpectedException (typeof (ArgumentException))]
+               public void PortBelow ()
+               {
+                       HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://go-mono.com");
+                       req.Host = "go-mono.com:-1";
+               }
+
+               [Test]
+               [ExpectedException (typeof (ArgumentException))]
+               public void PortAbove ()
+               {
+                       HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://go-mono.com");
+                       req.Host = "go-mono.com:65536";
+               }
+
+               [Test]
+               public void InvalidNamesThatWork ()
+               {
+                       HttpWebRequest req = (HttpWebRequest) WebRequest.Create ("http://go-mono.com");
+                       req.Host = "-";
+                       req.Host = "-.-";
+                       req.Host = "รก";
+                       req.Host = new string ('a', 64); // Should fail. Max. is 63.
+                       string s = new string ('a', 100);
+                       req.Host = s + "." + s + "." + s + "." + s + "." + s + "." + s; // Over 255 bytes
+               }
+#endif
                class ListenerScope : IDisposable {
                        EventWaitHandle completed;
                        public HttpListener listener;