diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/DotNetOpenAuth.Test/Messaging/MessagingUtilitiesTests.cs | 30 | ||||
-rw-r--r-- | src/DotNetOpenAuth/Messaging/MessagingUtilities.cs | 14 |
2 files changed, 41 insertions, 3 deletions
diff --git a/src/DotNetOpenAuth.Test/Messaging/MessagingUtilitiesTests.cs b/src/DotNetOpenAuth.Test/Messaging/MessagingUtilitiesTests.cs index 26ce4cd..5a4c78e 100644 --- a/src/DotNetOpenAuth.Test/Messaging/MessagingUtilitiesTests.cs +++ b/src/DotNetOpenAuth.Test/Messaging/MessagingUtilitiesTests.cs @@ -11,8 +11,10 @@ namespace DotNetOpenAuth.Test.Messaging using System.Collections.Specialized; using System.IO; using System.Net; + using System.Text.RegularExpressions; using System.Web; using DotNetOpenAuth.Messaging; + using DotNetOpenAuth.Test.Mocks; using Microsoft.VisualStudio.TestTools.UnitTesting; [TestClass] @@ -139,5 +141,33 @@ namespace DotNetOpenAuth.Test.Messaging Assert.AreEqual("%C2%80", MessagingUtilities.EscapeUriDataStringRfc3986("\u0080")); Assert.AreEqual("%E3%80%81", MessagingUtilities.EscapeUriDataStringRfc3986("\u3001")); } + + /// <summary> + /// Verifies the overall format of the multipart POST is correct. + /// </summary> + [TestMethod] + public void PostMultipart() { + var httpHandler = new TestWebRequestHandler(); + bool callbackTriggered = false; + httpHandler.Callback = req => { + Match m = Regex.Match(req.ContentType, "multipart/form-data; boundary=(.+)"); + Assert.IsTrue(m.Success, "Content-Type HTTP header not set correctly."); + string boundary = m.Groups[1].Value; + string expectedEntity = "--{0}\r\nContent-Disposition: form-data; name=\"a\"\r\n\r\nb\r\n--{0}--\r\n"; + expectedEntity = string.Format(expectedEntity, boundary); + string actualEntity = httpHandler.RequestEntityAsString; + Assert.AreEqual(expectedEntity, actualEntity); + callbackTriggered = true; + Assert.AreEqual(req.ContentLength, actualEntity.Length); + IncomingWebResponse resp = new CachedDirectWebResponse(); + return resp; + }; + var request = (HttpWebRequest)WebRequest.Create("http://someserver"); + var parts = new [] { + MultipartPostPart.CreateFormPart("a", "b"), + }; + request.PostMultipart(httpHandler, parts); + Assert.IsTrue(callbackTriggered); + } } } diff --git a/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs b/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs index 3f77a25..f57cf6b 100644 --- a/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs +++ b/src/DotNetOpenAuth/Messaging/MessagingUtilities.cs @@ -141,7 +141,7 @@ namespace DotNetOpenAuth.Messaging { } /// <summary> - /// Sends an multipart HTTP POST request (useful for posting files). + /// Sends a multipart HTTP POST request (useful for posting files). /// </summary> /// <param name="request">The HTTP request.</param> /// <param name="requestHandler">The request handler.</param> @@ -153,13 +153,19 @@ namespace DotNetOpenAuth.Messaging { Contract.Requires<ArgumentNullException>(parts != null); Reporting.RecordFeatureUse("MessagingUtilities.PostMultipart"); + parts = parts.CacheGeneratedResults(); string boundary = Guid.NewGuid().ToString(); + string initialPartLeadingBoundary = string.Format(CultureInfo.InvariantCulture, "--{0}\r\n", boundary); string partLeadingBoundary = string.Format(CultureInfo.InvariantCulture, "\r\n--{0}\r\n", boundary); string finalTrailingBoundary = string.Format(CultureInfo.InvariantCulture, "\r\n--{0}--\r\n", boundary); request.Method = "POST"; request.ContentType = "multipart/form-data; boundary=" + boundary; - request.ContentLength = parts.Sum(p => partLeadingBoundary.Length + p.Length) + finalTrailingBoundary.Length; + long contentLength = parts.Sum(p => partLeadingBoundary.Length + p.Length) + finalTrailingBoundary.Length; + if (parts.Any()) { + contentLength -= 2; // the initial part leading boundary has no leading \r\n + } + request.ContentLength = contentLength; // Setting the content-encoding to "utf-8" causes Google to reply // with a 415 UnsupportedMediaType. But adding it doesn't buy us @@ -169,8 +175,10 @@ namespace DotNetOpenAuth.Messaging { var requestStream = requestHandler.GetRequestStream(request); try { StreamWriter writer = new StreamWriter(requestStream, Channel.PostEntityEncoding); + bool firstPart = true; foreach (var part in parts) { - writer.Write(partLeadingBoundary); + writer.Write(firstPart ? initialPartLeadingBoundary : partLeadingBoundary); + firstPart = false; part.Serialize(writer); part.Dispose(); } |