Merge pull request #3591 from directhex/mono_libdir_fallback
[mono.git] / mcs / class / System.Net.Http / System.Net.Http / HttpClientHandler.cs
index 026171a4f7ad6139b6264cab2ddbae3633235e4e..a3335ea5506ffe67aafedba5773301d48b9cee77 100644 (file)
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
+using System.Collections.Generic;
+using System.Security.Authentication;
+using System.Security.Cryptography.X509Certificates;
 using System.Threading;
 using System.Threading.Tasks;
 using System.Collections.Specialized;
 using System.Net.Http.Headers;
+using System.Net.Security;
+using System.Linq;
 
 namespace System.Net.Http
 {
@@ -232,6 +237,7 @@ namespace System.Net.Http
                {
                        var wr = new HttpWebRequest (request.RequestUri);
                        wr.ThrowOnError = false;
+                       wr.AllowWriteStreamBuffering = false;
 
                        wr.ConnectionGroupName = connectionGroupName;
                        wr.Method = request.Method.Method;
@@ -243,8 +249,6 @@ namespace System.Net.Http
                                wr.KeepAlive = request.Headers.ConnectionClose != true;
                        }
 
-                       wr.ServicePoint.Expect100Continue = request.Headers.ExpectContinue == true;
-
                        if (allowAutoRedirect) {
                                wr.AllowAutoRedirect = true;
                                wr.MaximumAutomaticRedirections = maxAutomaticRedirections;
@@ -268,14 +272,36 @@ namespace System.Net.Http
 
                        if (useProxy) {
                                wr.Proxy = proxy;
+                       } else {
+                               // Disables default WebRequest.DefaultWebProxy value
+                               wr.Proxy = null;
                        }
 
+                       wr.ServicePoint.Expect100Continue = request.Headers.ExpectContinue == true;
+
                        // Add request headers
                        var headers = wr.Headers;
                        foreach (var header in request.Headers) {
-                               foreach (var value in header.Value) {
-                                       headers.AddValue (header.Key, value);
+                               var values = header.Value;
+                               if (header.Key == "Host") {
+                                       //
+                                       // Host must be explicitly set for HttpWebRequest
+                                       //
+                                       wr.Host = request.Headers.Host;
+                                       continue;
+                               }
+
+                               if (header.Key == "Transfer-Encoding") {
+                                       // Chunked Transfer-Encoding is never set for HttpWebRequest. It's detected
+                                       // from ContentLength by HttpWebRequest
+                                       values = values.Where (l => l != "chunked");
                                }
+
+                               var values_formated = HttpRequestHeaders.GetSingleHeaderString (header.Key, values);
+                               if (values_formated == null)
+                                       continue;
+
+                               headers.AddInternal (header.Key, values_formated);
                        }
                        
                        return wr;
@@ -318,14 +344,29 @@ namespace System.Net.Http
 
                        try {
                                using (cancellationToken.Register (l => ((HttpWebRequest)l).Abort (), wrequest)) {
-                                       if (request.Content != null) {
+                                       var content = request.Content;
+                                       if (content != null) {
                                                var headers = wrequest.Headers;
-                                               foreach (var header in request.Content.Headers) {
+
+                                               foreach (var header in content.Headers) {
                                                        foreach (var value in header.Value) {
-                                                               headers.AddValue (header.Key, value);
+                                                               headers.AddInternal (header.Key, value);
                                                        }
                                                }
 
+                                               //
+                                               // Content length has to be set because HttpWebRequest is running without buffering
+                                               //
+                                               var contentLength = content.Headers.ContentLength;
+                                               if (contentLength != null) {
+                                                       wrequest.ContentLength = contentLength.Value;
+                                               } else {
+                                                       await content.LoadIntoBufferAsync (MaxRequestContentBufferSize).ConfigureAwait (false);
+                                                       wrequest.ContentLength = content.Headers.ContentLength.Value;
+                                               }
+
+                                               wrequest.ResendContentFactory = content.CopyTo;
+
                                                var stream = await wrequest.GetRequestStreamAsync ().ConfigureAwait (false);
                                                await request.Content.CopyToAsync (stream).ConfigureAwait (false);
                                        } else if (HttpMethod.Post.Equals (request.Method) || HttpMethod.Put.Equals (request.Method) || HttpMethod.Delete.Equals (request.Method)) {
@@ -339,7 +380,9 @@ namespace System.Net.Http
                                }
                        } catch (WebException we) {
                                if (we.Status != WebExceptionStatus.RequestCanceled)
-                                       throw;
+                                       throw new HttpRequestException ("An error occurred while sending the request", we);
+                       } catch (System.IO.IOException ex) {
+                               throw new HttpRequestException ("An error occurred while sending the request", ex);
                        }
 
                        if (cancellationToken.IsCancellationRequested) {
@@ -350,5 +393,74 @@ namespace System.Net.Http
                        
                        return CreateResponseMessage (wresponse, request, cancellationToken);
                }
+
+#if NETSTANDARD
+               public bool CheckCertificateRevocationList {
+                       get {
+                               throw new NotImplementedException ();
+                       }
+                       set {
+                               throw new NotImplementedException ();
+                       }
+               }
+
+               public X509CertificateCollection ClientCertificates {
+                       get {
+                               throw new NotImplementedException ();
+                       }
+               }
+
+               public ICredentials DefaultProxyCredentials {
+                       get {
+                               throw new NotImplementedException ();
+                       }
+                       set {
+                               throw new NotImplementedException ();
+                       }
+               }
+
+               public int MaxConnectionsPerServer {
+                       get {
+                               throw new NotImplementedException ();
+                       }
+                       set {
+                               throw new NotImplementedException ();
+                       }
+               }
+
+               public int MaxResponseHeadersLength {
+                       get {
+                               throw new NotImplementedException ();
+                       }
+                       set {
+                               throw new NotImplementedException ();
+                       }
+               }
+
+               public IDictionary<string,object> Properties {
+                       get {
+                               throw new NotImplementedException ();
+                       }
+               }
+
+               public Func<HttpRequestMessage,X509Certificate2,X509Chain,SslPolicyErrors,bool> ServerCertificateCustomValidationCallback {
+                       get {
+                               throw new NotImplementedException ();
+                       }
+                       set {
+                               throw new NotImplementedException ();
+                       }
+               }
+
+               public SslProtocols SslProtocols {
+                       get {
+                               throw new NotImplementedException ();
+                       }
+                       set {
+                               throw new NotImplementedException ();
+                       }
+               }
+
+#endif
        }
 }