diff --git a/src/NzbDrone.Common.Test/Http/HttpClientFixture.cs b/src/NzbDrone.Common.Test/Http/HttpClientFixture.cs
index a1eb10fda..302bae8dd 100644
--- a/src/NzbDrone.Common.Test/Http/HttpClientFixture.cs
+++ b/src/NzbDrone.Common.Test/Http/HttpClientFixture.cs
@@ -11,36 +11,22 @@ using NzbDrone.Test.Common.Categories;
 using NLog;
 using NzbDrone.Common.TPL;
 using Moq;
+using NzbDrone.Common.Http.Dispatchers;
 
 namespace NzbDrone.Common.Test.Http
 {
-    [TestFixture(true)]
-    [TestFixture(false)]
     [IntegrationTest]
-    public class HttpClientFixture : TestBase<HttpClient>
-    {
-        private bool _forceCurl;
-
-        public HttpClientFixture(bool forceCurl)
-        {
-            _forceCurl = forceCurl;
-        }
-        
+    [TestFixture(typeof(ManagedHttpDispatcher))]
+    [TestFixture(typeof(CurlHttpDispatcher))]
+    public class HttpClientFixture<TDispatcher> : TestBase<HttpClient> where TDispatcher : IHttpDispatcher
+    {        
         [SetUp]
         public void SetUp()
         {
             Mocker.SetConstant<ICacheManager>(Mocker.Resolve<CacheManager>());
             Mocker.SetConstant<IRateLimitService>(Mocker.Resolve<RateLimitService>());
             Mocker.SetConstant<IEnumerable<IHttpRequestInterceptor>>(new IHttpRequestInterceptor[0]);
-
-            if (_forceCurl)
-            {
-                Mocker.SetConstant<IHttpDispatcher>(Mocker.Resolve<CurlHttpDispatcher>());
-            }
-            else
-            {
-                Mocker.SetConstant<IHttpDispatcher>(Mocker.Resolve<ManagedHttpDispatcher>());
-            }
+            Mocker.SetConstant<IHttpDispatcher>(Mocker.Resolve<TDispatcher>());
         }
 
         [Test]
diff --git a/src/NzbDrone.Common/Http/CurlHttpClient.cs b/src/NzbDrone.Common/Http/Dispatchers/CurlHttpDispatcher.cs
similarity index 59%
rename from src/NzbDrone.Common/Http/CurlHttpClient.cs
rename to src/NzbDrone.Common/Http/Dispatchers/CurlHttpDispatcher.cs
index c7af89cac..2bd3f1bd2 100644
--- a/src/NzbDrone.Common/Http/CurlHttpClient.cs
+++ b/src/NzbDrone.Common/Http/Dispatchers/CurlHttpDispatcher.cs
@@ -1,5 +1,4 @@
-using System;
-using System.Collections.Generic;
+using System;
 using System.IO;
 using System.IO.Compression;
 using System.Linq;
@@ -13,20 +12,13 @@ using NzbDrone.Common.EnvironmentInfo;
 using NzbDrone.Common.Extensions;
 using NzbDrone.Common.Instrumentation;
 
-namespace NzbDrone.Common.Http
+namespace NzbDrone.Common.Http.Dispatchers
 {
-    public class CurlHttpClient
+    public class CurlHttpDispatcher : IHttpDispatcher
     {
-        private static Logger Logger = NzbDroneLogger.GetLogger(typeof(CurlHttpClient));
         private static readonly Regex ExpiryDate = new Regex(@"(expires=)([^;]+)", RegexOptions.IgnoreCase | RegexOptions.Compiled);
 
-        public CurlHttpClient()
-        {
-            if (!CheckAvailability())
-            {
-                throw new ApplicationException("Curl failed to initialize.");
-            }
-        }
+        private static readonly Logger _logger = NzbDroneLogger.GetLogger(typeof(CurlHttpDispatcher));
 
         public static bool CheckAvailability()
         {
@@ -36,13 +28,23 @@ namespace NzbDrone.Common.Http
             }
             catch (Exception ex)
             {
-                Logger.TraceException("Initializing curl failed", ex);
+                _logger.TraceException("Initializing curl failed", ex);
                 return false;
             }
         }
 
-        public HttpResponse GetResponse(HttpRequest httpRequest, HttpWebRequest webRequest)
+        public HttpResponse GetResponse(HttpRequest request, CookieContainer cookies)
         {
+            if (!CheckAvailability())
+            {
+                throw new ApplicationException("Curl failed to initialize.");
+            }
+
+            if (request.NetworkCredential != null)
+            {
+                throw new NotImplementedException("Credentials not supported for curl dispatcher.");
+            }
+
             lock (CurlGlobalHandle.Instance)
             {
                 Stream responseStream = new MemoryStream();
@@ -61,33 +63,47 @@ namespace NzbDrone.Common.Http
                         headerStream.Write(b, 0, s * n);
                         return s * n;
                     };
+                    
+                    curlEasy.Url = request.Url.AbsoluteUri;
+                    switch (request.Method)
+                    {
+                        case HttpMethod.GET:
+                            curlEasy.HttpGet = true;
+                            break;
+
+                        case HttpMethod.POST:
+                            curlEasy.Post = true;
+                            break;
 
-                    curlEasy.UserAgent = webRequest.UserAgent;
-                    curlEasy.FollowLocation = webRequest.AllowAutoRedirect;
-                    curlEasy.HttpGet = webRequest.Method == "GET";
-                    curlEasy.Post = webRequest.Method == "POST";
-                    curlEasy.Put = webRequest.Method == "PUT";
-                    curlEasy.Url = webRequest.RequestUri.AbsoluteUri;
+                        case HttpMethod.PUT:
+                            curlEasy.Put = true;
+                            break;
+
+                        default:
+                            throw new NotSupportedException(string.Format("HttpCurl method {0} not supported", request.Method));
+                    }
+                    curlEasy.UserAgent = UserAgentBuilder.UserAgent;
+                    curlEasy.FollowLocation = request.AllowAutoRedirect;
 
                     if (OsInfo.IsWindows)
                     {
                         curlEasy.CaInfo = "curl-ca-bundle.crt";
                     }
 
-                    if (webRequest.CookieContainer != null)
+                    if (cookies != null)
                     {
-                        curlEasy.Cookie = webRequest.CookieContainer.GetCookieHeader(webRequest.RequestUri);
+                        curlEasy.Cookie = cookies.GetCookieHeader(request.Url);
                     }
 
-                    if (!httpRequest.Body.IsNullOrWhiteSpace())
+                    if (!request.Body.IsNullOrWhiteSpace())
                     {
                         // TODO: This might not go well with encoding.
-                        curlEasy.PostFieldSize = httpRequest.Body.Length;
-                        curlEasy.SetOpt(CurlOption.CopyPostFields, httpRequest.Body);
+                        curlEasy.PostFieldSize = request.Body.Length;
+                        curlEasy.SetOpt(CurlOption.CopyPostFields, request.Body);
                     }
 
                     // Yes, we have to keep a ref to the object to prevent corrupting the unmanaged state
-                    using (var httpRequestHeaders = SerializeHeaders(webRequest))
+                    using (var httpRequestHeaders = SerializeHeaders(request))
                     {
                         curlEasy.HttpHeader = httpRequestHeaders;
 
@@ -99,60 +115,38 @@ namespace NzbDrone.Common.Http
                         }
                     }
 
-                    var webHeaderCollection = ProcessHeaderStream(webRequest, headerStream);
-                    var responseData = ProcessResponseStream(webRequest, responseStream, webHeaderCollection);
+                    var webHeaderCollection = ProcessHeaderStream(request, cookies, headerStream);
+                    var responseData = ProcessResponseStream(request, responseStream, webHeaderCollection);
 
                     var httpHeader = new HttpHeader(webHeaderCollection);
 
-                    return new HttpResponse(httpRequest, httpHeader, responseData, (HttpStatusCode)curlEasy.ResponseCode);
+                    return new HttpResponse(request, httpHeader, responseData, (HttpStatusCode)curlEasy.ResponseCode);
                 }
             }
         }
 
-        private CurlSlist SerializeHeaders(HttpWebRequest webRequest)
+        private CurlSlist SerializeHeaders(HttpRequest request)
         {
-            if (webRequest.SendChunked)
-            {
-                throw new NotSupportedException("Chunked transfer is not supported");
-            }
-
-            if (webRequest.ContentLength > 0)
+            if (!request.Headers.ContainsKey("Accept-Encoding"))
             {
-                webRequest.Headers.Add("Content-Length", webRequest.ContentLength.ToString());
+                request.Headers.Add("Accept-Encoding", "gzip");
             }
 
-            if (webRequest.AutomaticDecompression.HasFlag(DecompressionMethods.GZip))
-            {
-                if (webRequest.AutomaticDecompression.HasFlag(DecompressionMethods.Deflate))
-                {
-                    webRequest.Headers.Add("Accept-Encoding", "gzip, deflate");
-                }
-                else
-                {
-                    webRequest.Headers.Add("Accept-Encoding", "gzip");
-                }
-            }
-            else
+            if (request.Headers.ContentType == null)
             {
-                if (webRequest.AutomaticDecompression.HasFlag(DecompressionMethods.Deflate))
-                {
-                    webRequest.Headers.Add("Accept-Encoding", "deflate");
-                }
+                request.Headers.ContentType = string.Empty;
             }
 
-
             var curlHeaders = new CurlSlist();
-            for (int i = 0; i < webRequest.Headers.Count; i++)
+            foreach (var header in request.Headers)
             {
-                curlHeaders.Append(webRequest.Headers.GetKey(i) + ": " + webRequest.Headers.Get(i));
+                curlHeaders.Append(header.Key + ": " + header.Value.ToString());
             }
 
-            curlHeaders.Append("Content-Type: " + webRequest.ContentType ?? string.Empty);
-
             return curlHeaders;
         }
 
-        private WebHeaderCollection ProcessHeaderStream(HttpWebRequest webRequest, Stream headerStream)
+        private WebHeaderCollection ProcessHeaderStream(HttpRequest request, CookieContainer cookies, Stream headerStream)
         {
             headerStream.Position = 0;
             var headerData = headerStream.ToBytes();
@@ -168,9 +162,9 @@ namespace NzbDrone.Common.Http
             }
 
             var setCookie = webHeaderCollection.Get("Set-Cookie");
-            if (setCookie != null && setCookie.Length > 0 && webRequest.CookieContainer != null)
+            if (setCookie != null && setCookie.Length > 0 && cookies != null)
             {
-                webRequest.CookieContainer.SetCookies(webRequest.RequestUri, FixSetCookieHeader(setCookie));
+                cookies.SetCookies(request.Url, FixSetCookieHeader(setCookie));
             }
 
             return webHeaderCollection;
@@ -180,30 +174,30 @@ namespace NzbDrone.Common.Http
         {
             // fix up the date if it was malformed
             var setCookieClean = ExpiryDate.Replace(setCookie, delegate(Match match)
-                                                    {
-                                                        string format = "ddd, dd-MMM-yyyy HH:mm:ss";
-                                                        DateTime dt = Convert.ToDateTime(match.Groups[2].Value);
-                                                        return match.Groups[1].Value + dt.ToUniversalTime().ToString(format) + " GMT";
-                                                    });
+            {
+                string format = "ddd, dd-MMM-yyyy HH:mm:ss";
+                DateTime dt = Convert.ToDateTime(match.Groups[2].Value);
+                return match.Groups[1].Value + dt.ToUniversalTime().ToString(format) + " GMT";
+            });
             return setCookieClean;
         }
 
-        private byte[] ProcessResponseStream(HttpWebRequest webRequest, Stream responseStream, WebHeaderCollection webHeaderCollection)
+        private byte[] ProcessResponseStream(HttpRequest request, Stream responseStream, WebHeaderCollection webHeaderCollection)
         {
             responseStream.Position = 0;
 
-            if (responseStream.Length != 0 && webRequest.AutomaticDecompression != DecompressionMethods.None)
+            if (responseStream.Length != 0)
             {
                 var encoding = webHeaderCollection["Content-Encoding"];
                 if (encoding != null)
                 {
-                    if (webRequest.AutomaticDecompression.HasFlag(DecompressionMethods.GZip) && encoding.IndexOf("gzip") != -1)
+                    if (encoding.IndexOf("gzip") != -1)
                     {
                         responseStream = new GZipStream(responseStream, CompressionMode.Decompress);
 
                         webHeaderCollection.Remove("Content-Encoding");
                     }
-                    else if (webRequest.AutomaticDecompression.HasFlag(DecompressionMethods.Deflate) && encoding.IndexOf("deflate") != -1)
+                    else if (encoding.IndexOf("deflate") != -1)
                     {
                         responseStream = new DeflateStream(responseStream, CompressionMode.Decompress);
 
diff --git a/src/NzbDrone.Common/Http/Dispatchers/FallbackHttpDispatcher.cs b/src/NzbDrone.Common/Http/Dispatchers/FallbackHttpDispatcher.cs
new file mode 100644
index 000000000..0fc64af8e
--- /dev/null
+++ b/src/NzbDrone.Common/Http/Dispatchers/FallbackHttpDispatcher.cs
@@ -0,0 +1,60 @@
+using System;
+using System.Net;
+using NLog;
+using NzbDrone.Common.Cache;
+using NzbDrone.Common.EnvironmentInfo;
+
+namespace NzbDrone.Common.Http.Dispatchers
+{
+    public class FallbackHttpDispatcher : IHttpDispatcher
+    {
+        private readonly Logger _logger;
+        private readonly ICached<bool> _curlTLSFallbackCache;
+        private readonly ManagedHttpDispatcher _managedDispatcher;
+        private readonly CurlHttpDispatcher _curlDispatcher;
+
+        public FallbackHttpDispatcher(ICached<bool> curlTLSFallbackCache, Logger logger)
+        {
+            _logger = logger;
+            _curlTLSFallbackCache = curlTLSFallbackCache;
+            _managedDispatcher = new ManagedHttpDispatcher();
+            _curlDispatcher = new CurlHttpDispatcher();
+        }
+
+        public HttpResponse GetResponse(HttpRequest request, CookieContainer cookies)
+        {
+            if (OsInfo.IsMonoRuntime && request.Url.Scheme == "https")
+            {
+                if (!_curlTLSFallbackCache.Find(request.Url.Host))
+                {
+                    try
+                    {
+                        return _managedDispatcher.GetResponse(request, cookies);
+                    }
+                    catch (Exception ex)
+                    {
+                        if (ex.ToString().Contains("The authentication or decryption has failed."))
+                        {
+                            _logger.Debug("https request failed in tls error for {0}, trying curl fallback.", request.Url.Host);
+
+                            _curlTLSFallbackCache.Set(request.Url.Host, true);
+                        }
+                        else
+                        {
+                            throw;
+                        }
+                    }
+                }
+
+                if (CurlHttpDispatcher.CheckAvailability())
+                {
+                    return _curlDispatcher.GetResponse(request, cookies);
+                }
+
+                _logger.Trace("Curl not available, using default WebClient.");
+            }
+
+            return _managedDispatcher.GetResponse(request, cookies);
+        }
+    }
+}
diff --git a/src/NzbDrone.Common/Http/Dispatchers/IHttpDispatcher.cs b/src/NzbDrone.Common/Http/Dispatchers/IHttpDispatcher.cs
new file mode 100644
index 000000000..45237a110
--- /dev/null
+++ b/src/NzbDrone.Common/Http/Dispatchers/IHttpDispatcher.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Net;
+using NLog;
+using NzbDrone.Common.Cache;
+using NzbDrone.Common.EnvironmentInfo;
+using NzbDrone.Common.Extensions;
+using NzbDrone.Common.TPL;
+
+namespace NzbDrone.Common.Http.Dispatchers
+{
+    public interface IHttpDispatcher
+    {
+        HttpResponse GetResponse(HttpRequest request, CookieContainer cookies);
+    }
+}
diff --git a/src/NzbDrone.Common/Http/Dispatchers/ManagedHttpDispatcher.cs b/src/NzbDrone.Common/Http/Dispatchers/ManagedHttpDispatcher.cs
new file mode 100644
index 000000000..d80e2b3ea
--- /dev/null
+++ b/src/NzbDrone.Common/Http/Dispatchers/ManagedHttpDispatcher.cs
@@ -0,0 +1,122 @@
+using System;
+using System.Net;
+using NzbDrone.Common.Extensions;
+
+namespace NzbDrone.Common.Http.Dispatchers
+{
+    public class ManagedHttpDispatcher : IHttpDispatcher
+    {
+        public HttpResponse GetResponse(HttpRequest request, CookieContainer cookies)
+        {
+            var webRequest = (HttpWebRequest)WebRequest.Create(request.Url);
+
+            // Deflate is not a standard and could break depending on implementation.
+            // we should just stick with the more compatible Gzip
+            //http://stackoverflow.com/questions/8490718/how-to-decompress-stream-deflated-with-java-util-zip-deflater-in-net
+            webRequest.AutomaticDecompression = DecompressionMethods.GZip;
+
+            webRequest.Credentials = request.NetworkCredential;
+            webRequest.Method = request.Method.ToString();
+            webRequest.UserAgent = UserAgentBuilder.UserAgent;
+            webRequest.KeepAlive = false;
+            webRequest.AllowAutoRedirect = request.AllowAutoRedirect;
+            webRequest.ContentLength = 0;
+            webRequest.CookieContainer = cookies;
+
+            if (request.Headers != null)
+            {
+                AddRequestHeaders(webRequest, request.Headers);
+            }
+
+            if (!request.Body.IsNullOrWhiteSpace())
+            {
+                var bytes = request.Headers.GetEncodingFromContentType().GetBytes(request.Body.ToCharArray());
+
+                webRequest.ContentLength = bytes.Length;
+                using (var writeStream = webRequest.GetRequestStream())
+                {
+                    writeStream.Write(bytes, 0, bytes.Length);
+                }
+            }
+
+            HttpWebResponse httpWebResponse;
+
+            try
+            {
+                httpWebResponse = (HttpWebResponse)webRequest.GetResponse();
+            }
+            catch (WebException e)
+            {
+                httpWebResponse = (HttpWebResponse)e.Response;
+
+                if (httpWebResponse == null)
+                {
+                    throw;
+                }
+            }
+
+            byte[] data = null;
+
+            using (var responseStream = httpWebResponse.GetResponseStream())
+            {
+                if (responseStream != null)
+                {
+                    data = responseStream.ToBytes();
+                }
+            }
+
+            return new HttpResponse(request, new HttpHeader(httpWebResponse.Headers), data, httpWebResponse.StatusCode);
+        }
+
+        protected virtual void AddRequestHeaders(HttpWebRequest webRequest, HttpHeader headers)
+        {
+            foreach (var header in headers)
+            {
+                switch (header.Key)
+                {
+                    case "Accept":
+                        webRequest.Accept = header.Value.ToString();
+                        break;
+                    case "Connection":
+                        webRequest.Connection = header.Value.ToString();
+                        break;
+                    case "Content-Length":
+                        webRequest.ContentLength = Convert.ToInt64(header.Value);
+                        break;
+                    case "Content-Type":
+                        webRequest.ContentType = header.Value.ToString();
+                        break;
+                    case "Date":
+                        webRequest.Date = (DateTime)header.Value;
+                        break;
+                    case "Expect":
+                        webRequest.Expect = header.Value.ToString();
+                        break;
+                    case "Host":
+                        webRequest.Host = header.Value.ToString();
+                        break;
+                    case "If-Modified-Since":
+                        webRequest.IfModifiedSince = (DateTime)header.Value;
+                        break;
+                    case "Range":
+                        throw new NotImplementedException();
+                        break;
+                    case "Referer":
+                        webRequest.Referer = header.Value.ToString();
+                        break;
+                    case "Transfer-Encoding":
+                        webRequest.TransferEncoding = header.Value.ToString();
+                        break;
+                    case "User-Agent":
+                        throw new NotSupportedException("User-Agent other than Sonarr not allowed.");
+                    case "Proxy-Connection":
+                        throw new NotImplementedException();
+                        break;
+                    default:
+                        webRequest.Headers.Add(header.Key, header.Value.ToString());
+                        break;
+                }
+            }
+        }
+    }
+}
diff --git a/src/NzbDrone.Common/Http/HttpClient.cs b/src/NzbDrone.Common/Http/HttpClient.cs
index bb6ba5313..f38811b5c 100644
--- a/src/NzbDrone.Common/Http/HttpClient.cs
+++ b/src/NzbDrone.Common/Http/HttpClient.cs
@@ -8,6 +8,7 @@ using NLog;
 using NzbDrone.Common.Cache;
 using NzbDrone.Common.EnvironmentInfo;
 using NzbDrone.Common.Extensions;
+using NzbDrone.Common.Http.Dispatchers;
 using NzbDrone.Common.TPL;
 
 namespace NzbDrone.Common.Http
@@ -23,119 +24,6 @@ namespace NzbDrone.Common.Http
         HttpResponse<T> Post<T>(HttpRequest request) where T : new();
     }
 
-    public interface IHttpDispatcher
-    {
-        HttpResponse GetResponse(HttpRequest request, HttpWebRequest webRequest);
-    }
-
-    public class ManagedHttpDispatcher : IHttpDispatcher
-    {
-        public HttpResponse GetResponse(HttpRequest request, HttpWebRequest webRequest)
-        {
-            if (!request.Body.IsNullOrWhiteSpace())
-            {
-                var bytes = request.Headers.GetEncodingFromContentType().GetBytes(request.Body.ToCharArray());
-
-                webRequest.ContentLength = bytes.Length;
-                using (var writeStream = webRequest.GetRequestStream())
-                {
-                    writeStream.Write(bytes, 0, bytes.Length);
-                }
-            }
-
-            HttpWebResponse httpWebResponse;
-
-            try
-            {
-                httpWebResponse = (HttpWebResponse)webRequest.GetResponse();
-            }
-            catch (WebException e)
-            {
-                httpWebResponse = (HttpWebResponse)e.Response;
-
-                if (httpWebResponse == null)
-                {
-                    throw;
-                }
-            }
-
-            Byte[] data = null;
-
-            using (var responseStream = httpWebResponse.GetResponseStream())
-            {
-                if (responseStream != null)
-                {
-                    data = responseStream.ToBytes();
-                }
-            }
-
-            return new HttpResponse(request, new HttpHeader(httpWebResponse.Headers), data, httpWebResponse.StatusCode);
-
-        }
-    }
-
-    public class CurlHttpDispatcher : IHttpDispatcher
-    {
-        public HttpResponse GetResponse(HttpRequest request, HttpWebRequest webRequest)
-        {
-            var curlClient = new CurlHttpClient();
-
-            return curlClient.GetResponse(request, webRequest);
-        }
-    }
-
-    public class FallbackHttpDispatcher : IHttpDispatcher
-    {
-        private readonly Logger _logger;
-        private readonly ICached<bool> _curlTLSFallbackCache;
-
-        public FallbackHttpDispatcher(ICached<bool> curlTLSFallbackCache, Logger logger)
-        {
-            _logger = logger;
-            _curlTLSFallbackCache = curlTLSFallbackCache;
-        }
-
-        public HttpResponse GetResponse(HttpRequest request, HttpWebRequest webRequest)
-        {
-
-            ManagedHttpDispatcher managedDispatcher = new ManagedHttpDispatcher();
-            CurlHttpDispatcher curlDispatcher = new CurlHttpDispatcher();
-
-            if (OsInfo.IsMonoRuntime && webRequest.RequestUri.Scheme == "https")
-            {
-                if (!_curlTLSFallbackCache.Find(webRequest.RequestUri.Host))
-                {
-                    try
-                    {
-                        return managedDispatcher.GetResponse(request, webRequest);
-                    }
-                    catch (Exception ex)
-                    {
-                        if (ex.ToString().Contains("The authentication or decryption has failed."))
-                        {
-                            _logger.Debug("https request failed in tls error for {0}, trying curl fallback.", webRequest.RequestUri.Host);
-
-                            _curlTLSFallbackCache.Set(webRequest.RequestUri.Host, true);
-                        }
-                        else
-                        {
-                            throw;
-                        }
-                    }
-                }
-
-                if (CurlHttpClient.CheckAvailability())
-                {
-                    return curlDispatcher.GetResponse(request, webRequest);
-                }
-
-                _logger.Trace("Curl not available, using default WebClient.");
-            }
-
-            return managedDispatcher.GetResponse(request, webRequest);
-        }
-    }
-
     public class HttpClient : IHttpClient
     {
         private readonly Logger _logger;
@@ -176,37 +64,23 @@ namespace NzbDrone.Common.Http
 
             _logger.Trace(request);
 
-            var webRequest = (HttpWebRequest)WebRequest.Create(request.Url);
-
-            // Deflate is not a standard and could break depending on implementation.
-            // we should just stick with the more compatible Gzip
-            //http://stackoverflow.com/questions/8490718/how-to-decompress-stream-deflated-with-java-util-zip-deflater-in-net
-            webRequest.AutomaticDecompression = DecompressionMethods.GZip;
-
-            webRequest.Credentials = request.NetworkCredential;
-            webRequest.Method = request.Method.ToString();
-            webRequest.UserAgent = UserAgentBuilder.UserAgent;
-            webRequest.KeepAlive = false;
-            webRequest.AllowAutoRedirect = request.AllowAutoRedirect;
-            webRequest.ContentLength = 0;
-
             var stopWatch = Stopwatch.StartNew();
 
-            if (request.Headers != null)
-            {
-                AddRequestHeaders(webRequest, request.Headers);
-            }
-
-            PrepareRequestCookies(request, webRequest);
+            var cookies = PrepareRequestCookies(request);
 
-            var response = _httpDispatcher.GetResponse(request, webRequest);
+            var response = _httpDispatcher.GetResponse(request, cookies);
 
-            HandleResponseCookies(request, webRequest);
+            HandleResponseCookies(request, cookies);
 
             stopWatch.Stop();
 
             _logger.Trace("{0} ({1:n0} ms)", response, stopWatch.ElapsedMilliseconds);
 
+            foreach (var interceptor in _requestInterceptors)
+            {
+                response = interceptor.PostResponse(response);
+            }
+
             if (!RuntimeInfoBase.IsProduction &&
                 (response.StatusCode == HttpStatusCode.Moved ||
                  response.StatusCode == HttpStatusCode.MovedPermanently ||
@@ -229,15 +103,10 @@ namespace NzbDrone.Common.Http
                 }
             }
 
-            foreach (var interceptor in _requestInterceptors)
-            {
-                response = interceptor.PostResponse(response);
-            }
-
             return response;
         }
 
-        private void PrepareRequestCookies(HttpRequest request, HttpWebRequest webRequest)
+        private CookieContainer PrepareRequestCookies(HttpRequest request)
         {
             lock (_cookieContainerCache)
             {
@@ -258,21 +127,15 @@ namespace NzbDrone.Common.Http
 
                 var requestCookies = persistentCookieContainer.GetCookies(request.Url);
 
-                if (requestCookies.Count == 0 && !request.StoreResponseCookie)
-                {
-                    return;
-                }
+                var cookieContainer = new CookieContainer();
 
-                if (webRequest.CookieContainer == null)
-                {
-                    webRequest.CookieContainer = new CookieContainer();
-                }
+                cookieContainer.Add(requestCookies);
 
-                webRequest.CookieContainer.Add(requestCookies);
+                return cookieContainer;
             }
         }
 
-        private void HandleResponseCookies(HttpRequest request, HttpWebRequest webRequest)
+        private void HandleResponseCookies(HttpRequest request, CookieContainer cookieContainer)
         {
             if (!request.StoreResponseCookie)
             {
@@ -283,7 +146,7 @@ namespace NzbDrone.Common.Http
             {
                 var persistentCookieContainer = _cookieContainerCache.Get("container", () => new CookieContainer());
 
-                var cookies = webRequest.CookieContainer.GetCookies(request.Url);
+                var cookies = cookieContainer.GetCookies(request.Url);
 
                 persistentCookieContainer.Add(cookies);
             }
@@ -349,56 +212,5 @@ namespace NzbDrone.Common.Http
             var response = Post(request);
             return new HttpResponse<T>(response);
         }
-
-        protected virtual void AddRequestHeaders(HttpWebRequest webRequest, HttpHeader headers)
-        {
-            foreach (var header in headers)
-            {
-                switch (header.Key)
-                {
-                    case "Accept":
-                        webRequest.Accept = header.Value.ToString();
-                        break;
-                    case "Connection":
-                        webRequest.Connection = header.Value.ToString();
-                        break;
-                    case "Content-Length":
-                        webRequest.ContentLength = Convert.ToInt64(header.Value);
-                        break;
-                    case "Content-Type":
-                        webRequest.ContentType = header.Value.ToString();
-                        break;
-                    case "Date":
-                        webRequest.Date = (DateTime)header.Value;
-                        break;
-                    case "Expect":
-                        webRequest.Expect = header.Value.ToString();
-                        break;
-                    case "Host":
-                        webRequest.Host = header.Value.ToString();
-                        break;
-                    case "If-Modified-Since":
-                        webRequest.IfModifiedSince = (DateTime)header.Value;
-                        break;
-                    case "Range":
-                        throw new NotImplementedException();
-                        break;
-                    case "Referer":
-                        webRequest.Referer = header.Value.ToString();
-                        break;
-                    case "Transfer-Encoding":
-                        webRequest.TransferEncoding = header.Value.ToString();
-                        break;
-                    case "User-Agent":
-                        throw new NotSupportedException("User-Agent other than Sonarr not allowed.");
-                    case "Proxy-Connection":
-                        throw new NotImplementedException();
-                        break;
-                    default:
-                        webRequest.Headers.Add(header.Key, header.Value.ToString());
-                        break;
-                }
-            }
-        }
     }
 }
\ No newline at end of file
diff --git a/src/NzbDrone.Common/NzbDrone.Common.csproj b/src/NzbDrone.Common/NzbDrone.Common.csproj
index 12ab380c6..e98d3689d 100644
--- a/src/NzbDrone.Common/NzbDrone.Common.csproj
+++ b/src/NzbDrone.Common/NzbDrone.Common.csproj
@@ -141,7 +141,10 @@
     <Compile Include="Extensions\UrlExtensions.cs" />
     <Compile Include="Extensions\XmlExtentions.cs" />
     <Compile Include="HashUtil.cs" />
-    <Compile Include="Http\CurlHttpClient.cs" />
+    <Compile Include="Http\Dispatchers\CurlHttpDispatcher.cs" />
+    <Compile Include="Http\Dispatchers\FallbackHttpDispatcher.cs" />
+    <Compile Include="Http\Dispatchers\IHttpDispatcher.cs" />
+    <Compile Include="Http\Dispatchers\ManagedHttpDispatcher.cs" />
     <Compile Include="Http\GZipWebClient.cs">
       <SubType>Component</SubType>
     </Compile>