Permalink
Browse files

NCBC-172: RestSharp is new default HTTP client for views

Change-Id: I624ea571dfb5cadaac4f889ece9c2c6a3a283dea
Reviewed-on: http://review.couchbase.org/23786
Reviewed-by: Saakshi Manocha <saakshi.manocha@globallogic.com>
Tested-by: Saakshi Manocha <saakshi.manocha@globallogic.com>
  • Loading branch information...
1 parent 1f27152 commit 8a7d7544b77bfe7d046e7723138d00be1d104080 @johnzablocki johnzablocki committed with saakshimanocha Jan 8, 2013
@@ -45,7 +45,7 @@
<add uri="http://localhost:8091/pools" />
</servers>
<documentNameTransformer type="Couchbase.Configuration.ProductionModeNameTransformer, Couchbase" />
- <httpClientFactory type="Couchbase.HammockHttpClientFactory, Couchbase" />
+ <httpClientFactory type="Couchbase.RestSharpHttpClientFactory, Couchbase" />
<socketPool connectionTimeout="00:00:30" />
</couchbase>
@@ -18,46 +18,46 @@ public class DefaultConfigurationSettingsTests
/// <summary>
/// @test: create couchbase client using configuration and http client is not set,
- /// then it creates instance of hammock http client
+ /// then it creates instance of RestSharp http client
/// @pre: Default configuration to initialize client in app.config
- /// @post: Test passes if result is of type hammock http client
+ /// @post: Test passes if result is of type RestSharp http client
/// </summary>
[Test]
- public void When_Using_Code_Config_And_Http_Client_Factory_Is_Not_Set_Hammock_Factory_Is_Default()
+ public void When_Using_Code_Config_And_Http_Client_Factory_Is_Not_Set_RestSharp_Factory_Is_Default()
{
var config = new CouchbaseClientConfiguration();
config.Urls.Add(new Uri("http://localhost:8091/pools"));
- Assert.That(config.HttpClientFactory, Is.InstanceOf<HammockHttpClientFactory>());
+ Assert.That(config.HttpClientFactory, Is.InstanceOf<RestSharpHttpClientFactory>());
- //HammockHttpClient is an internal class to the Couchbase assembly,
+ //RestSharpHttpClient is an internal class to the Couchbase assembly,
//therefore the explicit type can't be checked for using Is.InstanceOf<T>
var typeName = (config.HttpClientFactory.Create(config.Urls[0], "", "", TimeSpan.FromMinutes(1), true).GetType().Name);
- Assert.That(typeName, Is.StringContaining("HammockHttpClient"));
+ Assert.That(typeName, Is.StringContaining("RestSharpHttpClient"));
}
/// <summary>
/// @test: create couchbase client using configuration from app.config and http client is not set,
- /// then it creates instance of hammock http client
+ /// then it creates instance of RestSharp http client
/// @pre: Default configuration to initialize client in app.config
- /// @post: Test passes if result is of type hammock http client
+ /// @post: Test passes if result is of type RestSharp http client
/// </summary>
[Test]
- public void When_Using_App_Config_And_Http_Client_Factory_Is_Not_Set_Hammock_Factory_Is_Default()
+ public void When_Using_App_Config_And_Http_Client_Factory_Is_Not_Set_RestSharp_Factory_Is_Default()
{
var config = ConfigurationManager.GetSection("min-config") as CouchbaseClientSection;
Assert.That(config, Is.Not.Null, "min-config section missing from app.config");
Assert.That(config.HttpClientFactory, Is.InstanceOf<ProviderElement<IHttpClientFactory>>());
- //HammockHttpClient is an internal class to the Couchbase assembly,
+ //RestSharpHttpClient is an internal class to the Couchbase assembly,
//therefore the explicit type can't be checked for using Is.InstanceOf<T>
var typeName = (config.HttpClientFactory.CreateInstance().Create(config.Servers.Urls.ToUriCollection()[0], "", "", TimeSpan.FromMinutes(1), true).GetType().Name);
- Assert.That(typeName, Is.StringContaining("HammockHttpClient"));
+ Assert.That(typeName, Is.StringContaining("RestSharpHttpClient"));
}
/// <summary>
/// @test: create couchbase client using configuration and http client is not set,
- /// then it creates instance of hammock http client. perform operations like storing key value,
+ /// then it creates instance of RestSharp http client. perform operations like storing key value,
/// the operations should all succeed
/// @pre: Default configuration to initialize client in app.config
/// @post: Test passes if all operations succeed
@@ -73,16 +73,16 @@ public void When_Using_App_Config_And_Http_Client_Factory_Is_Not_Set_Operations_
var client = new CouchbaseClient(config);
var kv = KeyValueUtils.GenerateKeyAndValue("default_config");
- var result = client.Store(StoreMode.Add, kv.Item1, kv.Item2);
- Assert.That(result, Is.True, "Store failed");
+ var result = client.ExecuteStore(StoreMode.Add, kv.Item1, kv.Item2);
+ Assert.That(result.Success, Is.True, "Store failed: " + result.Message);
var value = client.Get(kv.Item1);
Assert.That(value, Is.StringMatching(kv.Item2));
}
/// <summary>
/// @test: create couchbase client using configuration from code and http client is not set,
- /// then it creates instance of hammock http client. perform operations like
+ /// then it creates instance of RestSharp http client. perform operations like
/// get and store and they should all pass
/// @pre: Default configuration to initialize client in app.config
/// @post: Test passes if all operations should happen successfully
@@ -92,16 +92,16 @@ public void When_Using_Code_Config_And_Http_Client_Factory_Is_Not_Set_Operations
{
var config = new CouchbaseClientConfiguration();
config.Urls.Add(new Uri("http://localhost:8091/pools"));
- Assert.That(config.HttpClientFactory, Is.InstanceOf<HammockHttpClientFactory>());
+ Assert.That(config.HttpClientFactory, Is.InstanceOf<RestSharpHttpClientFactory>());
Assert.That(config, Is.Not.Null, "min-config section missing from app.config");
- Assert.That(config.HttpClientFactory, Is.InstanceOf<HammockHttpClientFactory>());
+ Assert.That(config.HttpClientFactory, Is.InstanceOf<RestSharpHttpClientFactory>());
var client = new CouchbaseClient(config);
var kv = KeyValueUtils.GenerateKeyAndValue("default_config");
- var result = client.Store(StoreMode.Add, kv.Item1, kv.Item2);
- Assert.That(result, Is.True, "Store failed");
+ var result = client.ExecuteStore(StoreMode.Add, kv.Item1, kv.Item2);
+ Assert.That(result.Success, Is.True, "Store failed: " + result.Message);
var value = client.Get(kv.Item1);
Assert.That(value, Is.StringMatching(kv.Item2));
@@ -25,7 +25,7 @@ public class CouchbaseClientConfiguration : ICouchbaseClientConfiguration
/// </summary>
public CouchbaseClientConfiguration()
{
- this.HttpClientFactory = HammockHttpClientFactory.Instance;
+ this.HttpClientFactory = RestSharpHttpClientFactory.Instance;
this.Urls = new List<Uri>();
@@ -134,7 +134,7 @@ protected override void PostDeserialize()
{
return new ProviderElement<IHttpClientFactory>()
{
- Type = typeof(HammockHttpClientFactory)
+ Type = typeof(RestSharpHttpClientFactory)
};
}
return (ProviderElement<IHttpClientFactory>)provider;
@@ -156,7 +156,7 @@ protected override void PostDeserialize()
if (this.clientFactory == null) {
var tmp = this.HttpClientFactory;
- this.clientFactory = tmp == null ? HammockHttpClientFactory.Instance : tmp.CreateInstance();
+ this.clientFactory = tmp == null ? RestSharpHttpClientFactory.Instance : tmp.CreateInstance();
}
Debug.Assert(this.clientFactory != null);
@@ -50,6 +50,9 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Newtonsoft.Json.4.5.1\lib\net40\Newtonsoft.Json.dll</HintPath>
</Reference>
+ <Reference Include="RestSharp">
+ <HintPath>..\packages\RestSharp.104.1\lib\net4\RestSharp.dll</HintPath>
+ </Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.configuration" />
@@ -157,6 +160,7 @@
<Compile Include="Protocol\CouchbaseOpCode.cs" />
<Compile Include="Protocol\ObserveResponse.cs" />
<Compile Include="Protocol\ObserveRequest.cs" />
+ <Compile Include="RestSharpHttpClient.cs" />
<Compile Include="Results\IObserveOperationResult.cs" />
<Compile Include="Results\ObserveOperationResult.cs" />
<Compile Include="Settings\ObserveSettings.cs" />
@@ -0,0 +1,164 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using RestSharp;
+using System.IO;
+using System.Net;
+
+namespace Couchbase
+{
+ public class RestSharpHttpClient : IHttpClient
+ {
+ private static readonly Enyim.Caching.ILog log = Enyim.Caching.LogManager.GetLogger(typeof(RestSharpHttpClient));
+ private const int DEFAULT_RETRY_COUNT = 3;
+
+ private readonly RestClient client;
+
+ public RestSharpHttpClient(Uri baseUri, string username, string password, TimeSpan timeout, bool shouldInitConnection)
+ {
+ client = new RestClient { BaseUrl = baseUri.ToString() };
+ client.Timeout = timeout.Milliseconds;
+
+ if (!string.IsNullOrEmpty(username) && !string.IsNullOrEmpty(password))
+ {
+ client.Authenticator = new HttpBasicAuthenticator(username, password);
+ }
+
+#if ! MONO
+ ServicePointManager.FindServicePoint(baseUri).SetTcpKeepAlive(true, 300, 30);
+#endif
+
+ //The first time a request is made to a URI, the ServicePointManager
+ //will create a ServicePoint to manage connections to a particular host
+ //This process is expensive and slows down the first created view.
+ //The call to BeginRequest is basically an async, no-op HTTP request to
+ //initialize the ServicePoint before the first view request is made.
+ if (shouldInitConnection) client.ExecuteAsync(new RestRequest(), (r) => {});
+ }
+
+ public IHttpRequest CreateRequest(string path)
+ {
+ return new RestSharpRequestWrapper(this.client, path);
+ }
+
+ #region [ HammockRequestWrapper ]
+
+ private class RestSharpRequestWrapper : IHttpRequest
+ {
+ private RestRequest request;
+ private RestClient client;
+ private HttpMethod method;
+
+ public RestSharpRequestWrapper(RestClient client, string path)
+ {
+ this.client = client;
+ this.method = HttpMethod.Get;
+ this.request = new RestRequest { Resource = path };
+ request.AddHeader("Accept", "application/json");
+ request.AddHeader("Content-Type", "application/json; charset=utf-8");
+ }
+
+ void IHttpRequest.AddParameter(string name, string value)
+ {
+ this.request.AddParameter(name, value);
+ }
+
+ IHttpResponse IHttpRequest.GetResponse()
+ {
+
+ switch (this.method)
+ {
+ case HttpMethod.Delete: this.request.Method = Method.DELETE; break;
+ case HttpMethod.Get: this.request.Method = Method.GET; break;
+ case HttpMethod.Head: this.request.Method = Method.HEAD; break;
+ case HttpMethod.Options: this.request.Method = Method.OPTIONS; break;
+ case HttpMethod.Post: this.request.Method = Method.POST; break;
+ case HttpMethod.Put: this.request.Method = Method.PUT; break;
+ default: throw new ArgumentOutOfRangeException("method: " + this.method);
+ }
+
+ var r = new RestSharpResponseWrapper(request);
+ r.ExecuteWith(this.client);
+
+ return r;
+ }
+
+ HttpMethod IHttpRequest.Method
+ {
+ get { return this.method; }
+ set { this.method = value; }
+ }
+ }
+
+ #endregion
+
+ #region [ HammockResponseWrapper ]
+
+ private class RestSharpResponseWrapper : IHttpResponse
+ {
+ private IRestRequest request;
+ private IRestResponse response;
+
+ public RestSharpResponseWrapper(RestRequest request)
+ {
+ this.request = request;
+ }
+
+ public void ExecuteWith(RestClient client)
+ {
+ this.response = client.Execute(request);
+
+ if (response.ErrorException != null) throw response.ErrorException;
+ if (response.StatusCode != System.Net.HttpStatusCode.OK)
+ throw new InvalidOperationException(String.Format("Server returned {0}: {1}, {2}", response.StatusCode, response.StatusDescription, response.Content));
+ }
+
+ Stream IHttpResponse.GetResponseStream()
+ {
+ return new MemoryStream(this.response.RawBytes);
+ }
+ }
+
+ #endregion
+
+ private int retryCount = DEFAULT_RETRY_COUNT;
+
+ int IHttpClient.RetryCount
+ {
+ get { return retryCount; }
+ set { retryCount = value; }
+ }
+ }
+
+ public class RestSharpHttpClientFactory : IHttpClientFactory
+ {
+ public static readonly IHttpClientFactory Instance = new RestSharpHttpClientFactory();
+
+ IHttpClient IHttpClientFactory.Create(Uri baseUri, string username, string password, TimeSpan timeout, bool shouldInitializeConnection)
+ {
+ return new RestSharpHttpClient(baseUri, username, password, timeout, shouldInitializeConnection);
+ }
+ }
+}
+
+#region [ License information ]
+/* ************************************************************
+ *
+ * @author Couchbase <info@couchbase.com>
+ * @copyright 2012 Couchbase, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ************************************************************/
+#endregion
@@ -2,4 +2,5 @@
<packages>
<package id="Hammock" version="1.2.9" />
<package id="Newtonsoft.Json" version="4.5.1" />
+ <package id="RestSharp" version="104.1" targetFramework="net40" />
</packages>
Binary file not shown.
Binary file not shown.
Oops, something went wrong.

0 comments on commit 8a7d754

Please sign in to comment.