From 4359037e04e28b63184eb9650bc0a1284150ab24 Mon Sep 17 00:00:00 2001 From: Kimura Youichi Date: Thu, 28 Apr 2016 10:19:33 +0900 Subject: [PATCH] =?utf8?q?IApiConnection=E3=81=ABmultipart/form-data?= =?utf8?q?=E3=82=92=E9=80=81=E4=BF=A1=E3=81=99=E3=82=8B=E3=81=9F=E3=82=81?= =?utf8?q?=E3=81=AE=E3=83=A1=E3=82=BD=E3=83=83=E3=83=89=E3=82=92=E8=BF=BD?= =?utf8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- .../Connection/TwitterApiConnectionTest.cs | 59 ++++++++++++++++++++++ OpenTween/Connection/IApiConnection.cs | 2 + OpenTween/Connection/TwitterApiConnection.cs | 40 +++++++++++++++ 3 files changed, 101 insertions(+) diff --git a/OpenTween.Tests/Connection/TwitterApiConnectionTest.cs b/OpenTween.Tests/Connection/TwitterApiConnectionTest.cs index 2fa3683f..8f340665 100644 --- a/OpenTween.Tests/Connection/TwitterApiConnectionTest.cs +++ b/OpenTween.Tests/Connection/TwitterApiConnectionTest.cs @@ -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(x.Content); + + var boundary = x.Content.Headers.ContentType.Parameters.Cast() + .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 + { + ["aaaa"] = "1111", + ["bbbb"] = "2222", + }; + var mediaParam = new Dictionary + { + ["media1"] = media, + }; + + var result = await apiConnection.PostLazyAsync(endpoint, param, mediaParam) + .ConfigureAwait(false); + + Assert.Equal("hogehoge", await result.LoadJsonAsync() + .ConfigureAwait(false)); + + Assert.Equal(0, mockHandler.QueueCount); + } + } + } } } diff --git a/OpenTween/Connection/IApiConnection.cs b/OpenTween/Connection/IApiConnection.cs index 8be76e0f..26915773 100644 --- a/OpenTween/Connection/IApiConnection.cs +++ b/OpenTween/Connection/IApiConnection.cs @@ -32,5 +32,7 @@ namespace OpenTween.Connection Task GetAsync(Uri uri, IDictionary param); Task> PostLazyAsync(Uri uri, IDictionary param); + + Task> PostLazyAsync(Uri uri, IDictionary param, IDictionary media); } } diff --git a/OpenTween/Connection/TwitterApiConnection.cs b/OpenTween/Connection/TwitterApiConnection.cs index 9d039a0d..7cd2d4a0 100644 --- a/OpenTween/Connection/TwitterApiConnection.cs +++ b/OpenTween/Connection/TwitterApiConnection.cs @@ -125,6 +125,46 @@ namespace OpenTween.Connection } } + public async Task> PostLazyAsync(Uri uri, IDictionary param, IDictionary 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(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; -- 2.11.0