/// <summary>
        /// パラメータを指定してリソースへアクセスし、レスポンスボディを返します。
        /// </summary>
        /// <param name="requestUrl"></param>
        /// <param name="method"></param>
        /// <param name="parameters"></param>
        /// <param name="resourceEndpoint">Rate Limitを認識するためのリソースのエンドポイント</param>
        /// <returns></returns>
        public String Request(Uri requestUrl, HttpMethod method, String parameters, String resourceEndpoint)
        {
            if (!String.IsNullOrEmpty(resourceEndpoint))
            {
                if (!CanRequest(resourceEndpoint))
                {
                    throw new Exception(String.Format("APIのリクエスト制限回数に達しました。({0}; リセット:{1})", resourceEndpoint, _rateLimitStatuses[resourceEndpoint].Reset));
                }
            }

            UriBuilder newUri = new UriBuilder(requestUrl);

            newUri.Query = newUri.Query.TrimStart('?') + ((newUri.Query.Length > 0) ? "&" : "") + parameters;

            var request = RequestInternal(newUri.Uri, method, Token, TokenSecret, parameters);

            Action <WebResponse> setRateLimit = (WebResponse response) =>
            {
                if (!String.IsNullOrEmpty(resourceEndpoint))
                {
                    if (!_rateLimitStatuses.ContainsKey(resourceEndpoint))
                    {
                        _rateLimitStatuses[resourceEndpoint] = new RateLimitStatus()
                        {
                            Remaining = 15
                        };
                    }
                    Int32 remaining;
                    Int64 reset;
                    if (Int32.TryParse(response.Headers["X-Rate-Limit-Remaining"], out remaining))
                    {
                        _rateLimitStatuses[resourceEndpoint].Remaining = remaining;
                    }
                    if (Int64.TryParse(response.Headers["X-Rate-Limit-Reset"], out reset))
                    {
                        _rateLimitStatuses[resourceEndpoint].Reset = new DateTime(1970, 1, 1, 0, 0, 0, 0).ToLocalTime().AddSeconds(reset);
                    }
                }
            };

            try
            {
                var response = request.GetResponse();
                setRateLimit(response);
            }
            catch (WebException webE)
            {
                if (webE.Response != null)
                {
                    setRateLimit(webE.Response);
                }
                throw;
            }

            return(ReadResponse(request));
        }
        /// <summary>
        /// パラメータを指定してリソースへアクセスし、レスポンスボディを返します。
        /// </summary>
        /// <param name="requestUrl"></param>
        /// <param name="method"></param>
        /// <param name="parameters"></param>
        /// <param name="resourceEndpoint">Rate Limitを認識するためのリソースのエンドポイント</param>
        /// <returns></returns>
        public String Request(Uri requestUrl, HttpMethod method, String parameters, String resourceEndpoint)
        {
            if (!String.IsNullOrEmpty(resourceEndpoint))
            {
                if (!CanRequest(resourceEndpoint))
                {
                    throw new Exception(String.Format("APIのリクエスト制限回数に達しました。({0}; リセット:{1})", resourceEndpoint, _rateLimitStatuses[resourceEndpoint].Reset));
                }
            }

            UriBuilder newUri = new UriBuilder(requestUrl);
            newUri.Query = newUri.Query.TrimStart('?') + ((newUri.Query.Length > 0) ? "&" : "") + parameters;

            var request = RequestInternal(newUri.Uri, method, Token, TokenSecret, parameters);

            Action<WebResponse> setRateLimit = (WebResponse response) =>
                                   {
                                       if (!String.IsNullOrEmpty(resourceEndpoint))
                                       {
                                           if (!_rateLimitStatuses.ContainsKey(resourceEndpoint))
                                           {
                                               _rateLimitStatuses[resourceEndpoint] = new RateLimitStatus() { Remaining = 15 };
                                           }
                                           Int32 remaining;
                                           Int64 reset;
                                           if (Int32.TryParse(response.Headers["X-Rate-Limit-Remaining"], out remaining))
                                           {
                                               _rateLimitStatuses[resourceEndpoint].Remaining = remaining;
                                           }
                                           if (Int64.TryParse(response.Headers["X-Rate-Limit-Reset"], out reset))
                                           {
                                               _rateLimitStatuses[resourceEndpoint].Reset = new DateTime(1970, 1, 1, 0, 0, 0, 0).ToLocalTime().AddSeconds(reset);
                                           }
                                       }
                                   };

            try
            {
                var response = request.GetResponse();
                setRateLimit(response);
            }
            catch (WebException webE)
            {
                setRateLimit(webE.Response);
                throw;
            }

            return ReadResponse(request);
        }