diff options
author | Andrew Arnott <andrewarnott@gmail.com> | 2009-12-09 09:21:44 -0800 |
---|---|---|
committer | Andrew Arnott <andrewarnott@gmail.com> | 2009-12-09 09:21:44 -0800 |
commit | 19a4772e2950b3de43280a3919b6dd31f32c708f (patch) | |
tree | 26c76e0c0e8e875ca17631be32f10f1577e24589 /src | |
parent | cd200079f11817ad1439c76c36cb888255db0d4e (diff) | |
download | DotNetOpenAuth-19a4772e2950b3de43280a3919b6dd31f32c708f.zip DotNetOpenAuth-19a4772e2950b3de43280a3919b6dd31f32c708f.tar.gz DotNetOpenAuth-19a4772e2950b3de43280a3919b6dd31f32c708f.tar.bz2 |
Made the last commit's fix unit testable, added 4 unit tests, and satisfied StyleCop.
Conflicts:
src/DotNetOpenAuth/Messaging/HttpRequestInfo.cs
Diffstat (limited to 'src')
-rw-r--r-- | src/DotNetOpenAuth.Test/Messaging/HttpRequestInfoTests.cs | 56 | ||||
-rw-r--r-- | src/DotNetOpenAuth/Messaging/HttpRequestInfo.cs | 63 |
2 files changed, 99 insertions, 20 deletions
diff --git a/src/DotNetOpenAuth.Test/Messaging/HttpRequestInfoTests.cs b/src/DotNetOpenAuth.Test/Messaging/HttpRequestInfoTests.cs index 05ac306..fd77746 100644 --- a/src/DotNetOpenAuth.Test/Messaging/HttpRequestInfoTests.cs +++ b/src/DotNetOpenAuth.Test/Messaging/HttpRequestInfoTests.cs @@ -5,6 +5,8 @@ //----------------------------------------------------------------------- namespace DotNetOpenAuth.Test.Messaging { + using System; + using System.Collections.Specialized; using System.Web; using DotNetOpenAuth.Messaging; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -92,5 +94,59 @@ namespace DotNetOpenAuth.Test.Messaging { HttpRequestInfo info = new HttpRequestInfo(); Assert.IsNull(info.QueryString["hi"]); } + + /// <summary> + /// Verifies SSL forwarders are correctly handled when they supply X_FORWARDED_PROTO and HOST + /// </summary> + [TestMethod] + public void GetPublicFacingUrlSSLForwarder1() { + HttpRequest req = new HttpRequest("a.aspx", "http://someinternalhost/a.aspx?a=b", "a=b"); + var serverVariables = new NameValueCollection(); + serverVariables["HTTP_X_FORWARDED_PROTO"] = "https"; + serverVariables["HTTP_HOST"] = "somehost"; + Uri actual = HttpRequestInfo.GetPublicFacingUrl(req, serverVariables); + Uri expected = new Uri("https://somehost/a.aspx?a=b"); + Assert.AreEqual(expected, actual); + } + + /// <summary> + /// Verifies SSL forwarders are correctly handled when they supply X_FORWARDED_PROTO and HOST:port + /// </summary> + [TestMethod] + public void GetPublicFacingUrlSSLForwarder2() { + HttpRequest req = new HttpRequest("a.aspx", "http://someinternalhost/a.aspx?a=b", "a=b"); + var serverVariables = new NameValueCollection(); + serverVariables["HTTP_X_FORWARDED_PROTO"] = "https"; + serverVariables["HTTP_HOST"] = "somehost:999"; + Uri actual = HttpRequestInfo.GetPublicFacingUrl(req, serverVariables); + Uri expected = new Uri("https://somehost:999/a.aspx?a=b"); + Assert.AreEqual(expected, actual); + } + + /// <summary> + /// Verifies SSL forwarders are correctly handled when they supply just HOST + /// </summary> + [TestMethod] + public void GetPublicFacingUrlSSLForwarder3() { + HttpRequest req = new HttpRequest("a.aspx", "http://someinternalhost/a.aspx?a=b", "a=b"); + var serverVariables = new NameValueCollection(); + serverVariables["HTTP_HOST"] = "somehost"; + Uri actual = HttpRequestInfo.GetPublicFacingUrl(req, serverVariables); + Uri expected = new Uri("http://somehost/a.aspx?a=b"); + Assert.AreEqual(expected, actual); + } + + /// <summary> + /// Verifies SSL forwarders are correctly handled when they supply just HOST:port + /// </summary> + [TestMethod] + public void GetPublicFacingUrlSSLForwarder4() { + HttpRequest req = new HttpRequest("a.aspx", "http://someinternalhost/a.aspx?a=b", "a=b"); + var serverVariables = new NameValueCollection(); + serverVariables["HTTP_HOST"] = "somehost:79"; + Uri actual = HttpRequestInfo.GetPublicFacingUrl(req, serverVariables); + Uri expected = new Uri("http://somehost:79/a.aspx?a=b"); + Assert.AreEqual(expected, actual); + } } } diff --git a/src/DotNetOpenAuth/Messaging/HttpRequestInfo.cs b/src/DotNetOpenAuth/Messaging/HttpRequestInfo.cs index 2fd7be4..9e9deb4 100644 --- a/src/DotNetOpenAuth/Messaging/HttpRequestInfo.cs +++ b/src/DotNetOpenAuth/Messaging/HttpRequestInfo.cs @@ -293,28 +293,24 @@ namespace DotNetOpenAuth.Messaging { } /// <summary> - /// Gets the query or form data from the original request (before any URL rewriting has occurred.) - /// </summary> - /// <returns>A set of name=value pairs.</returns> - [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "Expensive call")] - internal NameValueCollection GetQueryOrFormFromContext() { - NameValueCollection query; - if (this.HttpMethod == "GET") { - query = this.QueryStringBeforeRewriting; - } else { - query = this.Form; - } - return query; - } - - /// <summary> /// Gets the public facing URL for the given incoming HTTP request. /// </summary> /// <param name="request">The request.</param> - /// <returns>The URI that the outside world used to create this request.</returns> - private static Uri GetPublicFacingUrl(HttpRequest request) { + /// <param name="serverVariables">The server variables to consider part of the request.</param> + /// <returns> + /// The URI that the outside world used to create this request. + /// </returns> + /// <remarks> + /// Although the <paramref name="serverVariables"/> value can be obtained from + /// <see cref="HttpRequest.ServerVariables"/>, it's useful to be able to pass them + /// in so we can simulate injected values from our unit tests since the actual property + /// is a read-only kind of <see cref="NameValueCollection"/>. + /// </remarks> + internal static Uri GetPublicFacingUrl(HttpRequest request, NameValueCollection serverVariables) { Contract.Requires(request != null); + Contract.Requires(serverVariables != null); ErrorUtilities.VerifyArgumentNotNull(request, "request"); + ErrorUtilities.VerifyArgumentNotNull(serverVariables, "serverVariables"); // Due to URL rewriting, cloud computing (i.e. Azure) // and web farms, etc., we have to be VERY careful about what @@ -323,10 +319,10 @@ namespace DotNetOpenAuth.Messaging { // HttpRequest.Url gives us the internal URL in a cloud environment, // So we use a variable that (at least from what I can tell) gives us // the public URL: - if (request.ServerVariables["HTTP_HOST"] != null) { + if (serverVariables["HTTP_HOST"] != null) { ErrorUtilities.VerifySupported(request.Url.Scheme == Uri.UriSchemeHttps || request.Url.Scheme == Uri.UriSchemeHttp, "Only HTTP and HTTPS are supported protocols."); - string scheme = request.ServerVariables["HTTP_X_FORWARDED_PROTO"] ?? request.Url.Scheme; - Uri hostAndPort = new Uri(scheme + Uri.SchemeDelimiter + request.ServerVariables["HTTP_HOST"]); + string scheme = serverVariables["HTTP_X_FORWARDED_PROTO"] ?? request.Url.Scheme; + Uri hostAndPort = new Uri(scheme + Uri.SchemeDelimiter + serverVariables["HTTP_HOST"]); UriBuilder publicRequestUri = new UriBuilder(request.Url); publicRequestUri.Scheme = scheme; publicRequestUri.Host = hostAndPort.Host; @@ -346,6 +342,33 @@ namespace DotNetOpenAuth.Messaging { } /// <summary> + /// Gets the query or form data from the original request (before any URL rewriting has occurred.) + /// </summary> + /// <returns>A set of name=value pairs.</returns> + [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "Expensive call")] + internal NameValueCollection GetQueryOrFormFromContext() { + NameValueCollection query; + if (this.HttpMethod == "GET") { + query = this.QueryStringBeforeRewriting; + } else { + query = this.Form; + } + return query; + } + + /// <summary> + /// Gets the public facing URL for the given incoming HTTP request. + /// </summary> + /// <param name="request">The request.</param> + /// <returns>The URI that the outside world used to create this request.</returns> + private static Uri GetPublicFacingUrl(HttpRequest request) { + Contract.Requires(request != null); + ErrorUtilities.VerifyArgumentNotNull(request, "request"); + + return GetPublicFacingUrl(request, request.ServerVariables); + } + + /// <summary> /// Makes up a reasonable guess at the raw URL from the possibly rewritten URL. /// </summary> /// <param name="url">A full URL.</param> |