OSDN Git Service

IApiConnectionにmultipart/form-dataを送信するためのメソッドを追加
authorKimura Youichi <kim.upsilon@bucyou.net>
Thu, 28 Apr 2016 01:19:33 +0000 (10:19 +0900)
committerKimura Youichi <kim.upsilon@bucyou.net>
Thu, 28 Apr 2016 14:55:12 +0000 (23:55 +0900)
OpenTween.Tests/Connection/TwitterApiConnectionTest.cs
OpenTween/Connection/IApiConnection.cs
OpenTween/Connection/TwitterApiConnection.cs

index 2fa3683..8f34066 100644 (file)
@@ -24,6 +24,7 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Net;
 using System.Net.Http;
+using System.Net.Http.Headers;
 using System.Reflection;
 using System.Runtime.InteropServices;
 using System.Text;
@@ -198,5 +199,63 @@ namespace OpenTween.Connection
                 Assert.Equal(0, mockHandler.QueueCount);
             }
         }
+
+        [Fact]
+        public async Task PostLazyAsync_MultipartTest()
+        {
+            using (var mockHandler = new HttpMessageHandlerMock())
+            using (var http = new HttpClient(mockHandler))
+            using (var apiConnection = new TwitterApiConnection("", ""))
+            {
+                apiConnection.http = http;
+
+                using (var image = TestUtils.CreateDummyImage())
+                using (var media = new MemoryImageMediaItem(image))
+                {
+                    mockHandler.Enqueue(async x =>
+                    {
+                        Assert.Equal(HttpMethod.Post, x.Method);
+                        Assert.Equal("https://api.twitter.com/1.1/hoge/tetete.json",
+                            x.RequestUri.AbsoluteUri);
+
+                        Assert.IsType<MultipartFormDataContent>(x.Content);
+
+                        var boundary = x.Content.Headers.ContentType.Parameters.Cast<NameValueHeaderValue>()
+                            .First(y => y.Name == "boundary").Value;
+
+                        // 前後のダブルクオーテーションを除去
+                        boundary = boundary.Substring(1, boundary.Length - 2);
+
+                        var body = await x.Content.ReadAsStringAsync()
+                            .ConfigureAwait(false);
+                        Assert.True(body.StartsWith("--" + boundary + "\r\n", StringComparison.Ordinal));
+
+                        return new HttpResponseMessage(HttpStatusCode.OK)
+                        {
+                            Content = new StringContent("\"hogehoge\""),
+                        };
+                    });
+
+                    var endpoint = new Uri("hoge/tetete.json", UriKind.Relative);
+                    var param = new Dictionary<string, string>
+                    {
+                        ["aaaa"] = "1111",
+                        ["bbbb"] = "2222",
+                    };
+                    var mediaParam = new Dictionary<string, IMediaItem>
+                    {
+                        ["media1"] = media,
+                    };
+
+                    var result = await apiConnection.PostLazyAsync<string>(endpoint, param, mediaParam)
+                        .ConfigureAwait(false);
+
+                    Assert.Equal("hogehoge", await result.LoadJsonAsync()
+                        .ConfigureAwait(false));
+
+                    Assert.Equal(0, mockHandler.QueueCount);
+                }
+            }
+        }
     }
 }
index 8be76e0..2691577 100644 (file)
@@ -32,5 +32,7 @@ namespace OpenTween.Connection
         Task<T> GetAsync<T>(Uri uri, IDictionary<string, string> param);
 
         Task<LazyJson<T>> PostLazyAsync<T>(Uri uri, IDictionary<string, string> param);
+
+        Task<LazyJson<T>> PostLazyAsync<T>(Uri uri, IDictionary<string, string> param, IDictionary<string, IMediaItem> media);
     }
 }
index 9d039a0..7cd2d4a 100644 (file)
@@ -125,6 +125,46 @@ namespace OpenTween.Connection
             }
         }
 
+        public async Task<LazyJson<T>> PostLazyAsync<T>(Uri uri, IDictionary<string, string> param, IDictionary<string, IMediaItem> media)
+        {
+            var requestUri = new Uri(this.RestApiBase, uri);
+            var request = new HttpRequestMessage(HttpMethod.Post, requestUri);
+
+            using (var postContent = new MultipartFormDataContent())
+            {
+                foreach (var kv in param)
+                    postContent.Add(new StringContent(kv.Value), kv.Key);
+
+                foreach (var kv in media)
+                    postContent.Add(new StreamContent(kv.Value.OpenRead()), kv.Key);
+
+                request.Content = postContent;
+
+                HttpResponseMessage response = null;
+                try
+                {
+                    response = await this.http.SendAsync(request, HttpCompletionOption.ResponseHeadersRead)
+                        .ConfigureAwait(false);
+
+                    await this.CheckStatusCode(response)
+                        .ConfigureAwait(false);
+
+                    var result = new LazyJson<T>(response);
+                    response = null;
+
+                    return result;
+                }
+                catch (OperationCanceledException ex)
+                {
+                    throw TwitterApiException.CreateFromException(ex);
+                }
+                finally
+                {
+                    response?.Dispose();
+                }
+            }
+        }
+
         protected async Task CheckStatusCode(HttpResponseMessage response)
         {
             var statusCode = response.StatusCode;