From 80f91b0cb827700ca1b85ae73713b92217ed4ded Mon Sep 17 00:00:00 2001 From: Per Lundberg Date: Wed, 30 Oct 2013 17:03:17 +0200 Subject: [PATCH 1/6] [Slightly OT...] Fixed very minor spelling error. --- RestSharp/RestClient.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RestSharp/RestClient.cs b/RestSharp/RestClient.cs index 5e00ebb10..2f8f8bf78 100644 --- a/RestSharp/RestClient.cs +++ b/RestSharp/RestClient.cs @@ -158,7 +158,7 @@ IDeserializer GetHandler(string contentType) /// /// Proxy to use for requests made by this client instance. - /// Passed on to underying WebRequest if set. + /// Passed on to underlying WebRequest if set. /// public IWebProxy Proxy { get; set; } #endif From dc5c3d669d0e3efd26f37b0bfdcdf3ba898507b7 Mon Sep 17 00:00:00 2001 From: Per Lundberg Date: Wed, 30 Oct 2013 17:22:06 +0200 Subject: [PATCH 2/6] Added TODO which someone could (and perhaps should) look into at some point. --- RestSharp/Http.Async.cs | 4 +++- RestSharp/Http.Sync.cs | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/RestSharp/Http.Async.cs b/RestSharp/Http.Async.cs index 69f4a6a33..9353c4b74 100644 --- a/RestSharp/Http.Async.cs +++ b/RestSharp/Http.Async.cs @@ -350,7 +350,9 @@ partial void AddAsyncHeaderActions() #endif } - private HttpWebRequest ConfigureAsyncWebRequest(string method, Uri url) + // TODO: Try to merge the shared parts between ConfigureWebRequest and ConfigureAsyncWebRequest (quite a bit of code + // TODO: duplication at the moment). + private HttpWebRequest ConfigureAsyncWebRequest(string method, Uri url) { #if SILVERLIGHT WebRequest.RegisterPrefix("http://", WebRequestCreator.ClientHttp); diff --git a/RestSharp/Http.Sync.cs b/RestSharp/Http.Sync.cs index 3adc1e317..70be1d60b 100644 --- a/RestSharp/Http.Sync.cs +++ b/RestSharp/Http.Sync.cs @@ -212,6 +212,8 @@ private void WriteRequestBody(HttpWebRequest webRequest) } } + // TODO: Try to merge the shared parts between ConfigureWebRequest and ConfigureAsyncWebRequest (quite a bit of code + // TODO: duplication at the moment). private HttpWebRequest ConfigureWebRequest(string method, Uri url) { var webRequest = (HttpWebRequest)WebRequest.Create(url); From 192f8c10a213c22772058dd7c39437e027a62d5a Mon Sep 17 00:00:00 2001 From: Per Lundberg Date: Thu, 31 Oct 2013 14:31:31 +0200 Subject: [PATCH 3/6] Added support for custom AuthenticationSchemes, to be able to test the upcoming Windows Authentication support. --- RestSharp.IntegrationTests/Helpers/SimpleServer.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/RestSharp.IntegrationTests/Helpers/SimpleServer.cs b/RestSharp.IntegrationTests/Helpers/SimpleServer.cs index 34e679b61..afa063721 100644 --- a/RestSharp.IntegrationTests/Helpers/SimpleServer.cs +++ b/RestSharp.IntegrationTests/Helpers/SimpleServer.cs @@ -10,9 +10,14 @@ public class SimpleServer : IDisposable readonly Action _handler; Thread _processor; - public static SimpleServer Create(string url, Action handler) + public static SimpleServer Create(string url, Action handler, AuthenticationSchemes authenticationSchemes = AuthenticationSchemes.Anonymous) { - var server = new SimpleServer(new HttpListener { Prefixes = { url } }, handler); + var listener = new HttpListener + { + Prefixes = { url }, + AuthenticationSchemes = authenticationSchemes + }; + var server = new SimpleServer(listener, handler); server.Start(); return server; } From bbf036a632482caac0483bdd5f8b5649c0e82ce5 Mon Sep 17 00:00:00 2001 From: Per Lundberg Date: Thu, 31 Oct 2013 14:33:03 +0200 Subject: [PATCH 4/6] Faking "after-the-fact" testing to look more TDD than it actually was. ;) Added a new IRestRequest & RestRequst UseDefaultCredentials property, which does what its name implies. --- .../RequestHeadTests.cs | 98 +++++++++++++++++++ .../RestSharp.IntegrationTests.csproj | 1 + RestSharp/IRestRequest.cs | 6 ++ RestSharp/RestRequest.cs | 6 ++ 4 files changed, 111 insertions(+) create mode 100644 RestSharp.IntegrationTests/RequestHeadTests.cs diff --git a/RestSharp.IntegrationTests/RequestHeadTests.cs b/RestSharp.IntegrationTests/RequestHeadTests.cs new file mode 100644 index 000000000..ce6593152 --- /dev/null +++ b/RestSharp.IntegrationTests/RequestHeadTests.cs @@ -0,0 +1,98 @@ +using System.Collections.Specialized; +using System.Linq; +using System.Net; +using RestSharp.IntegrationTests.Helpers; +using Xunit; + +namespace RestSharp.IntegrationTests +{ + public class RequestHeadTests + { + private const string BASE_URL = "http://localhost:8080/"; + + public RequestHeadTests() + { + RequestHeadCapturer.Initialize(); + } + + [Fact] + public void Does_Not_Pass_Default_Credentials_When_Server_Does_Not_Negotiate() + { + const Method httpMethod = Method.GET; + using (SimpleServer.Create(BASE_URL, Handlers.Generic())) + { + var client = new RestClient(BASE_URL); + var request = new RestRequest(RequestHeadCapturer.RESOURCE, httpMethod) + { + UseDefaultCredentials = true + }; + + client.Execute(request); + + Assert.NotNull(RequestHeadCapturer.CapturedHeaders); + var keys = RequestHeadCapturer.CapturedHeaders.Keys.Cast().ToArray(); + Assert.False(keys.Contains("Authorization"), "Authorization header was present in HTTP request from client, even though server does not use the Negotiate scheme"); + } + } + + [Fact] + public void Passes_Default_Credentials_When_UseDefaultCredentials_Is_True() + { + const Method httpMethod = Method.GET; + using (SimpleServer.Create(BASE_URL, Handlers.Generic(), AuthenticationSchemes.Negotiate)) + { + var client = new RestClient(BASE_URL); + var request = new RestRequest(RequestHeadCapturer.RESOURCE, httpMethod) + { + UseDefaultCredentials = true + }; + + var response = client.Execute(request); + + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.NotNull(RequestHeadCapturer.CapturedHeaders); + var keys = RequestHeadCapturer.CapturedHeaders.Keys.Cast().ToArray(); + Assert.True(keys.Contains("Authorization"), "Authorization header not present in HTTP request from client, even though UseDefaultCredentials = true"); + } + } + + [Fact] + public void Does_Not_Pass_Default_Credentials_When_UseDefaultCredentials_Is_False() + { + const Method httpMethod = Method.GET; + using (SimpleServer.Create(BASE_URL, Handlers.Generic(), AuthenticationSchemes.Negotiate)) + { + var client = new RestClient(BASE_URL); + var request = new RestRequest(RequestHeadCapturer.RESOURCE, httpMethod) + { + // UseDefaultCredentials is currently false by default, but to make the test more robust in case that ever + // changes, it's better to explicitly set it here. + UseDefaultCredentials = false + }; + + var response = client.Execute(request); + + Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); + Assert.Null(RequestHeadCapturer.CapturedHeaders); + } + } + + private class RequestHeadCapturer + { + public const string RESOURCE = "Capture"; + + public static NameValueCollection CapturedHeaders { get; set; } + + public static void Initialize() + { + CapturedHeaders = null; + } + + public static void Capture(HttpListenerContext context) + { + var request = context.Request; + CapturedHeaders = request.Headers; + } + } + } +} \ No newline at end of file diff --git a/RestSharp.IntegrationTests/RestSharp.IntegrationTests.csproj b/RestSharp.IntegrationTests/RestSharp.IntegrationTests.csproj index 3872ba5bb..5be3f9c41 100644 --- a/RestSharp.IntegrationTests/RestSharp.IntegrationTests.csproj +++ b/RestSharp.IntegrationTests/RestSharp.IntegrationTests.csproj @@ -76,6 +76,7 @@ + diff --git a/RestSharp/IRestRequest.cs b/RestSharp/IRestRequest.cs index 97033dc3a..4de8a85af 100644 --- a/RestSharp/IRestRequest.cs +++ b/RestSharp/IRestRequest.cs @@ -118,6 +118,12 @@ public interface IRestRequest /// int Attempts { get; } + /// + /// Determine whether or not the "default credentials" (e.g. the user account under which the current process is running) + /// will be sent along to the server. The default is false. + /// + bool UseDefaultCredentials { get; set; } + #if FRAMEWORK /// /// Adds a file to the Files collection to be included with a POST or PUT request diff --git a/RestSharp/RestRequest.cs b/RestSharp/RestRequest.cs index d039f8711..758fb98ff 100644 --- a/RestSharp/RestRequest.cs +++ b/RestSharp/RestRequest.cs @@ -51,6 +51,12 @@ public class RestRequest : IRestRequest /// public Action ResponseWriter { get; set; } + /// + /// Determine whether or not the "default credentials" (e.g. the user account under which the current process is running) + /// will be sent along to the server. The default is false. + /// + public bool UseDefaultCredentials { get; set; } + /// /// Default constructor /// From 03eb13c23ebe205eeda7c31b49ec52c927525a92 Mon Sep 17 00:00:00 2001 From: Per Lundberg Date: Thu, 31 Oct 2013 14:37:10 +0200 Subject: [PATCH 5/6] Implemented the support for UseDefaultCredentials in the various layers involved. Note that the integration tests currently only tests the Http.Sync.cs implementation - an async test could also be added if needed. --- RestSharp/Http.Async.cs | 8 ++++---- RestSharp/Http.Sync.cs | 6 +++--- RestSharp/Http.cs | 6 ++++++ RestSharp/IHttp.cs | 1 + RestSharp/RestClient.cs | 4 ++-- 5 files changed, 16 insertions(+), 9 deletions(-) diff --git a/RestSharp/Http.Async.cs b/RestSharp/Http.Async.cs index 9353c4b74..afa9108b8 100644 --- a/RestSharp/Http.Async.cs +++ b/RestSharp/Http.Async.cs @@ -350,16 +350,16 @@ partial void AddAsyncHeaderActions() #endif } - // TODO: Try to merge the shared parts between ConfigureWebRequest and ConfigureAsyncWebRequest (quite a bit of code - // TODO: duplication at the moment). - private HttpWebRequest ConfigureAsyncWebRequest(string method, Uri url) + // TODO: Try to merge the shared parts between ConfigureWebRequest and ConfigureAsyncWebRequest (quite a bit of code + // TODO: duplication at the moment). + private HttpWebRequest ConfigureAsyncWebRequest(string method, Uri url) { #if SILVERLIGHT WebRequest.RegisterPrefix("http://", WebRequestCreator.ClientHttp); WebRequest.RegisterPrefix("https://", WebRequestCreator.ClientHttp); #endif var webRequest = (HttpWebRequest)WebRequest.Create(url); - webRequest.UseDefaultCredentials = false; + webRequest.UseDefaultCredentials = UseDefaultCredentials; AppendHeaders(webRequest); AppendCookies(webRequest); diff --git a/RestSharp/Http.Sync.cs b/RestSharp/Http.Sync.cs index 70be1d60b..4efd86a79 100644 --- a/RestSharp/Http.Sync.cs +++ b/RestSharp/Http.Sync.cs @@ -212,12 +212,12 @@ private void WriteRequestBody(HttpWebRequest webRequest) } } - // TODO: Try to merge the shared parts between ConfigureWebRequest and ConfigureAsyncWebRequest (quite a bit of code - // TODO: duplication at the moment). + // TODO: Try to merge the shared parts between ConfigureWebRequest and ConfigureAsyncWebRequest (quite a bit of code + // TODO: duplication at the moment). private HttpWebRequest ConfigureWebRequest(string method, Uri url) { var webRequest = (HttpWebRequest)WebRequest.Create(url); - webRequest.UseDefaultCredentials = false; + webRequest.UseDefaultCredentials = UseDefaultCredentials; ServicePointManager.Expect100Continue = false; AppendHeaders(webRequest); diff --git a/RestSharp/Http.cs b/RestSharp/Http.cs index a1ef10059..5dfe0f5e6 100644 --- a/RestSharp/Http.cs +++ b/RestSharp/Http.cs @@ -135,6 +135,12 @@ protected bool HasFiles /// public int? MaxRedirects { get; set; } #endif + /// + /// Determine whether or not the "default credentials" (e.g. the user account under which the current process is running) + /// will be sent along to the server. + /// + public bool UseDefaultCredentials { get; set; } + /// /// HTTP headers to be sent with request /// diff --git a/RestSharp/IHttp.cs b/RestSharp/IHttp.cs index c12e9f55e..0538b250f 100644 --- a/RestSharp/IHttp.cs +++ b/RestSharp/IHttp.cs @@ -42,6 +42,7 @@ public interface IHttp X509CertificateCollection ClientCertificates { get; set; } int? MaxRedirects { get; set; } #endif + bool UseDefaultCredentials { get; set; } IList Headers { get; } IList Parameters { get; } diff --git a/RestSharp/RestClient.cs b/RestSharp/RestClient.cs index 2f8f8bf78..08309a08f 100644 --- a/RestSharp/RestClient.cs +++ b/RestSharp/RestClient.cs @@ -295,11 +295,11 @@ private string EncodeParameters(IRestRequest request, IEnumerable par private void ConfigureHttp(IRestRequest request, IHttp http) { http.AlwaysMultipartFormData = request.AlwaysMultipartFormData; + http.UseDefaultCredentials = request.UseDefaultCredentials; + http.ResponseWriter = request.ResponseWriter; http.CookieContainer = CookieContainer; - http.ResponseWriter = request.ResponseWriter; - // move RestClient.DefaultParameters into Request.Parameters foreach (var p in DefaultParameters) { From 6c3f31423c39897adc9500b850edacbae7e538db Mon Sep 17 00:00:00 2001 From: Per Lundberg Date: Thu, 31 Oct 2013 14:51:09 +0200 Subject: [PATCH 6/6] Fixed whitespace... Was spaces by mistake. --- RestSharp.IntegrationTests/Helpers/SimpleServer.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/RestSharp.IntegrationTests/Helpers/SimpleServer.cs b/RestSharp.IntegrationTests/Helpers/SimpleServer.cs index afa063721..0087b9b0a 100644 --- a/RestSharp.IntegrationTests/Helpers/SimpleServer.cs +++ b/RestSharp.IntegrationTests/Helpers/SimpleServer.cs @@ -12,11 +12,11 @@ public class SimpleServer : IDisposable public static SimpleServer Create(string url, Action handler, AuthenticationSchemes authenticationSchemes = AuthenticationSchemes.Anonymous) { - var listener = new HttpListener - { - Prefixes = { url }, - AuthenticationSchemes = authenticationSchemes - }; + var listener = new HttpListener + { + Prefixes = { url }, + AuthenticationSchemes = authenticationSchemes + }; var server = new SimpleServer(listener, handler); server.Start(); return server;