Merge pull request #13747 from directhex/dependency_tracking_is_hard
[mono-project.git] / mcs / class / System.Net.Http / HttpClientEx.cs
blobfd5621c22e385cd48fd3f56fc3f01e59e4a16a20
1 using System;
2 using System.IO;
3 using System.Net;
4 #if XAMCORE_2_0
5 using CoreFoundation;
6 using Foundation;
7 using ObjCRuntime;
8 #elif MONOMAC
9 using MonoMac.CoreFoundation;
10 using MonoMac.Foundation;
11 using MonoMac.ObjCRuntime;
12 #else
13 using MonoTouch.CoreFoundation;
14 using MonoTouch.Foundation;
15 using MonoTouch.ObjCRuntime;
16 #endif
18 #if SYSTEM_NET_HTTP && !MONOMAC
19 namespace System.Net.Http {
21 public partial class HttpClient {
23 public HttpClient ()
24 : this (GetDefaultHandler (), true)
28 // note: the linker will re-write this to only reference the selected handler
29 // but we want this to work "as expected" even if the application is not being linked
30 static HttpMessageHandler GetDefaultHandler ()
32 #if MONOTOUCH_WATCH
33 // There's only one valid handler type for watchOS
34 return new NSUrlSessionHandler ();
35 #else
36 return RuntimeOptions.GetHttpMessageHandler ();
37 #endif
40 #else
41 // due to historical reasons (around CFNetwork) Xamarin.Mac includes this inside it's profile assembly
42 // and not a custom System.Net.Http assembly
43 namespace Foundation {
44 #endif
46 partial class NSUrlSessionHandler {
48 bool allowAutoRedirect;
49 ICredentials credentials;
50 bool sentRequest;
52 public bool AllowAutoRedirect {
53 get {
54 return allowAutoRedirect;
56 set {
57 EnsureModifiability ();
58 allowAutoRedirect = value;
62 public ICredentials Credentials {
63 get {
64 return credentials;
66 set {
67 EnsureModifiability ();
68 credentials = value;
72 internal void EnsureModifiability ()
74 if (sentRequest)
75 throw new InvalidOperationException (
76 "This instance has already started one or more requests. " +
77 "Properties can only be modified before sending the first request.");
80 // almost identical to ModernHttpClient version but it uses the constants from monotouch.dll | Xamarin.[iOS|WatchOS|TVOS].dll
81 static Exception createExceptionForNSError(NSError error)
83 // var webExceptionStatus = WebExceptionStatus.UnknownError;
85 var innerException = new NSErrorException(error);
87 // errors that exists in both share the same error code, so we can use a single switch/case
88 // this also ease watchOS integration as if does not expose CFNetwork but (I would not be
89 // surprised if it)could return some of it's error codes
90 #if MONOTOUCH_WATCH
91 if (error.Domain == NSError.NSUrlErrorDomain) {
92 #else
93 if ((error.Domain == NSError.NSUrlErrorDomain) || (error.Domain == NSError.CFNetworkErrorDomain)) {
94 #endif
95 // Parse the enum into a web exception status or exception. Some
96 // of these values don't necessarily translate completely to
97 // what WebExceptionStatus supports, so made some best guesses
98 // here. For your reading pleasure, compare these:
100 // Apple docs: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Miscellaneous/Foundation_Constants/index.html#//apple_ref/doc/constant_group/URL_Loading_System_Error_Codes
101 // .NET docs: http://msdn.microsoft.com/en-us/library/system.net.webexceptionstatus(v=vs.110).aspx
102 switch ((NSUrlError) (long) error.Code) {
103 case NSUrlError.Cancelled:
104 case NSUrlError.UserCancelledAuthentication:
105 #if !MONOTOUCH_WATCH
106 case (NSUrlError) NSNetServicesStatus.CancelledError:
107 #endif
108 // No more processing is required so just return.
109 return new OperationCanceledException(error.LocalizedDescription, innerException);
110 // case NSUrlError.BadURL:
111 // case NSUrlError.UnsupportedURL:
112 // case NSUrlError.CannotConnectToHost:
113 // case NSUrlError.ResourceUnavailable:
114 // case NSUrlError.NotConnectedToInternet:
115 // case NSUrlError.UserAuthenticationRequired:
116 // case NSUrlError.InternationalRoamingOff:
117 // case NSUrlError.CallIsActive:
118 // case NSUrlError.DataNotAllowed:
119 // #if !MONOTOUCH_WATCH
120 // case (NSUrlError) CFNetworkErrors.Socks5BadCredentials:
121 // case (NSUrlError) CFNetworkErrors.Socks5UnsupportedNegotiationMethod:
122 // case (NSUrlError) CFNetworkErrors.Socks5NoAcceptableMethod:
123 // case (NSUrlError) CFNetworkErrors.HttpAuthenticationTypeUnsupported:
124 // case (NSUrlError) CFNetworkErrors.HttpBadCredentials:
125 // case (NSUrlError) CFNetworkErrors.HttpBadURL:
126 // #endif
127 // webExceptionStatus = WebExceptionStatus.ConnectFailure;
128 // break;
129 // case NSUrlError.TimedOut:
130 // #if !MONOTOUCH_WATCH
131 // case (NSUrlError) CFNetworkErrors.NetServiceTimeout:
132 // #endif
133 // webExceptionStatus = WebExceptionStatus.Timeout;
134 // break;
135 // case NSUrlError.CannotFindHost:
136 // case NSUrlError.DNSLookupFailed:
137 // #if !MONOTOUCH_WATCH
138 // case (NSUrlError) CFNetworkErrors.HostNotFound:
139 // case (NSUrlError) CFNetworkErrors.NetServiceDnsServiceFailure:
140 // #endif
141 // webExceptionStatus = WebExceptionStatus.NameResolutionFailure;
142 // break;
143 // case NSUrlError.DataLengthExceedsMaximum:
144 // webExceptionStatus = WebExceptionStatus.MessageLengthLimitExceeded;
145 // break;
146 // case NSUrlError.NetworkConnectionLost:
147 // #if !MONOTOUCH_WATCH
148 // case (NSUrlError) CFNetworkErrors.HttpConnectionLost:
149 // #endif
150 // webExceptionStatus = WebExceptionStatus.ConnectionClosed;
151 // break;
152 // case NSUrlError.HTTPTooManyRedirects:
153 // case NSUrlError.RedirectToNonExistentLocation:
154 // #if !MONOTOUCH_WATCH
155 // case (NSUrlError) CFNetworkErrors.HttpRedirectionLoopDetected:
156 // #endif
157 // webExceptionStatus = WebExceptionStatus.ProtocolError;
158 // break;
159 // case NSUrlError.RequestBodyStreamExhausted:
160 // #if !MONOTOUCH_WATCH
161 // case (NSUrlError) CFNetworkErrors.SocksUnknownClientVersion:
162 // case (NSUrlError) CFNetworkErrors.SocksUnsupportedServerVersion:
163 // case (NSUrlError) CFNetworkErrors.HttpParseFailure:
164 // #endif
165 // webExceptionStatus = WebExceptionStatus.SendFailure;
166 // break;
167 // case NSUrlError.BadServerResponse:
168 // case NSUrlError.ZeroByteResource:
169 // case NSUrlError.CannotDecodeRawData:
170 // case NSUrlError.CannotDecodeContentData:
171 // case NSUrlError.CannotParseResponse:
172 // case NSUrlError.FileDoesNotExist:
173 // case NSUrlError.FileIsDirectory:
174 // case NSUrlError.NoPermissionsToReadFile:
175 // case NSUrlError.CannotLoadFromNetwork:
176 // case NSUrlError.CannotCreateFile:
177 // case NSUrlError.CannotOpenFile:
178 // case NSUrlError.CannotCloseFile:
179 // case NSUrlError.CannotWriteToFile:
180 // case NSUrlError.CannotRemoveFile:
181 // case NSUrlError.CannotMoveFile:
182 // case NSUrlError.DownloadDecodingFailedMidStream:
183 // case NSUrlError.DownloadDecodingFailedToComplete:
184 // #if !MONOTOUCH_WATCH
185 // case (NSUrlError) CFNetworkErrors.Socks4RequestFailed:
186 // case (NSUrlError) CFNetworkErrors.Socks4IdentdFailed:
187 // case (NSUrlError) CFNetworkErrors.Socks4IdConflict:
188 // case (NSUrlError) CFNetworkErrors.Socks4UnknownStatusCode:
189 // case (NSUrlError) CFNetworkErrors.Socks5BadState:
190 // case (NSUrlError) CFNetworkErrors.Socks5BadResponseAddr:
191 // case (NSUrlError) CFNetworkErrors.CannotParseCookieFile:
192 // case (NSUrlError) CFNetworkErrors.NetServiceUnknown:
193 // case (NSUrlError) CFNetworkErrors.NetServiceCollision:
194 // case (NSUrlError) CFNetworkErrors.NetServiceNotFound:
195 // case (NSUrlError) CFNetworkErrors.NetServiceInProgress:
196 // case (NSUrlError) CFNetworkErrors.NetServiceBadArgument:
197 // case (NSUrlError) CFNetworkErrors.NetServiceInvalid:
198 // #endif
199 // webExceptionStatus = WebExceptionStatus.ReceiveFailure;
200 // break;
201 // case NSUrlError.SecureConnectionFailed:
202 // webExceptionStatus = WebExceptionStatus.SecureChannelFailure;
203 // break;
204 // case NSUrlError.ServerCertificateHasBadDate:
205 // case NSUrlError.ServerCertificateHasUnknownRoot:
206 // case NSUrlError.ServerCertificateNotYetValid:
207 // case NSUrlError.ServerCertificateUntrusted:
208 // case NSUrlError.ClientCertificateRejected:
209 // case NSUrlError.ClientCertificateRequired:
210 // webExceptionStatus = WebExceptionStatus.TrustFailure;
211 // break;
212 // #if !MONOTOUCH_WATCH
213 // case (NSUrlError) CFNetworkErrors.HttpProxyConnectionFailure:
214 // case (NSUrlError) CFNetworkErrors.HttpBadProxyCredentials:
215 // case (NSUrlError) CFNetworkErrors.PacFileError:
216 // case (NSUrlError) CFNetworkErrors.PacFileAuth:
217 // case (NSUrlError) CFNetworkErrors.HttpsProxyConnectionFailure:
218 // case (NSUrlError) CFNetworkErrors.HttpsProxyFailureUnexpectedResponseToConnectMethod:
219 // webExceptionStatus = WebExceptionStatus.RequestProhibitedByProxy;
220 // break;
221 // #endif
225 // Always create a WebException so that it can be handled by the client.
226 return new WebException(error.LocalizedDescription, innerException); //, webExceptionStatus, response: null);