OSDN Git Service

例外発生時にDisposeが適切に呼ばれるようにする (CA2000)
[opentween/open-tween.git] / OpenTween / Connection / OAuthHandler.cs
1 // OpenTween - Client of Twitter
2 // Copyright (c) 2015 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
3 // All rights reserved.
4 //
5 // This file is part of OpenTween.
6 //
7 // This program is free software; you can redistribute it and/or modify it
8 // under the terms of the GNU General Public License as published by the Free
9 // Software Foundation; either version 3 of the License, or (at your option)
10 // any later version.
11 //
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 // for more details.
16 //
17 // You should have received a copy of the GNU General Public License along
18 // with this program. If not, see <http://www.gnu.org/licenses/>, or write to
19 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
20 // Boston, MA 02110-1301, USA.
21
22 using System;
23 using System.Collections.Generic;
24 using System.Diagnostics.CodeAnalysis;
25 using System.Linq;
26 using System.Net.Http;
27 using System.Text;
28 using System.Threading;
29 using System.Threading.Tasks;
30 using System.Web;
31
32 namespace OpenTween.Connection
33 {
34     /// <summary>
35     /// HttpClientで使用するOAuthハンドラー
36     /// </summary>
37     public class OAuthHandler : DelegatingHandler
38     {
39         public string ConsumerKey { get; }
40         public string ConsumerSecret { get; }
41         public string AccessToken { get; }
42         public string AccessSecret { get; }
43
44         [SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope")]
45         public OAuthHandler(string consumerKey, string consumerSecret, string accessToken, string accessSecret)
46             : this(new HttpClientHandler(), consumerKey, consumerSecret, accessToken, accessSecret)
47         {
48         }
49
50         public OAuthHandler(HttpMessageHandler innerHandler, string consumerKey, string consumerSecret, string accessToken, string accessSecret)
51             : base(innerHandler)
52         {
53             this.ConsumerKey = consumerKey;
54             this.ConsumerSecret = consumerSecret;
55             this.AccessToken = accessToken;
56             this.AccessSecret = accessSecret;
57         }
58
59         protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
60         {
61             var query = await GetParameters(request.RequestUri, request.Content)
62                 .ConfigureAwait(false);
63
64             var credential = OAuthUtility.CreateAuthorization(request.Method.ToString().ToUpperInvariant(), request.RequestUri, query,
65                 this.ConsumerKey, this.ConsumerSecret, this.AccessToken, this.AccessSecret);
66             request.Headers.TryAddWithoutValidation("Authorization", credential);
67
68             return await base.SendAsync(request, cancellationToken)
69                 .ConfigureAwait(false);
70         }
71
72         /// <summary>
73         /// OAuthの署名の対象となるパラメータを抽出します
74         /// </summary>
75         internal static async Task<IEnumerable<KeyValuePair<string, string>>> GetParameters(Uri requestUri, HttpContent content)
76         {
77             var parameters = Enumerable.Empty<KeyValuePair<string, string>>();
78
79             var postContent = content as FormUrlEncodedContent;
80             if (postContent != null)
81             {
82                 var query = await postContent.ReadAsStringAsync()
83                     .ConfigureAwait(false);
84
85                 var postParams = HttpUtility.ParseQueryString(query);
86                 var postParamsKvp = postParams.AllKeys.Cast<string>()
87                     .Select(x => new KeyValuePair<string, string>(x, postParams[x]));
88                 parameters = parameters.Concat(postParamsKvp);
89             }
90
91             var getParams = HttpUtility.ParseQueryString(requestUri.Query);
92             var getParamsKvp = getParams.AllKeys.Cast<string>()
93                 .Select(x => new KeyValuePair<string, string>(x, getParams[x]));
94             parameters = parameters.Concat(getParamsKvp);
95
96             return parameters;
97         }
98     }
99 }