2 // System.Net.WebRequest
5 // Lawrence Pit (loz@cable.a2000.nl)
6 // Marek Safar (marek.safar@gmail.com)
8 // Copyright 2011 Xamarin Inc.
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 using System.Collections;
32 using System.Collections.Specialized;
33 using System.Configuration;
35 using System.Reflection;
36 using System.Runtime.Serialization;
37 using System.Globalization;
38 using System.Net.Configuration;
39 using System.Net.Security;
40 using System.Net.Cache;
41 using System.Security.Principal;
43 using System.Threading.Tasks;
47 using ConfigurationException = System.ArgumentException;
49 namespace System.Net.Configuration {
57 internal abstract class WebRequest : ISerializable {
60 public abstract class WebRequest : MarshalByRefObject, ISerializable {
62 static HybridDictionary prefixes = new HybridDictionary ();
63 static bool isDefaultWebProxySet;
64 static IWebProxy defaultWebProxy;
65 static RequestCachePolicy defaultCachePolicy;
66 static MethodInfo cfGetDefaultProxy;
72 if (Platform.IsMacOS) {
74 Type type = Type.GetType ("MonoTouch.CoreFoundation.CFNetwork, monotouch");
76 Type type = Type.GetType ("MonoMac.CoreFoundation.CFNetwork, monomac");
79 cfGetDefaultProxy = type.GetMethod ("GetDefaultProxy");
83 IWebRequestCreate http = new HttpRequestCreator ();
84 RegisterPrefix ("http", http);
85 RegisterPrefix ("https", http);
87 RegisterPrefix ("file", new FileWebRequestCreator ());
88 RegisterPrefix ("ftp", new FtpRequestCreator ());
91 defaultCachePolicy = new HttpRequestCachePolicy (HttpRequestCacheLevel.NoCacheNoStore);
93 object cfg = ConfigurationManager.GetSection ("system.net/webRequestModules");
94 WebRequestModulesSection s = cfg as WebRequestModulesSection;
96 foreach (WebRequestModuleElement el in
98 AddPrefix (el.Prefix, el.Type);
102 ConfigurationSettings.GetConfig ("system.net/webRequestModules");
106 protected WebRequest ()
110 protected WebRequest (SerializationInfo serializationInfo, StreamingContext streamingContext)
114 static Exception GetMustImplement ()
116 return new NotImplementedException ("This method must be implemented in derived classes");
121 private AuthenticationLevel authentication_level = AuthenticationLevel.MutualAuthRequested;
123 public AuthenticationLevel AuthenticationLevel
126 return(authentication_level);
129 authentication_level = value;
133 [MonoTODO ("Implement the caching system. Currently always returns a policy with the NoCacheNoStore level")]
134 public virtual RequestCachePolicy CachePolicy
136 get { return DefaultCachePolicy; }
141 public virtual string ConnectionGroupName {
142 get { throw GetMustImplement (); }
143 set { throw GetMustImplement (); }
146 public virtual long ContentLength {
147 get { throw GetMustImplement (); }
148 set { throw GetMustImplement (); }
151 public virtual string ContentType {
152 get { throw GetMustImplement (); }
153 set { throw GetMustImplement (); }
156 public virtual ICredentials Credentials {
157 get { throw GetMustImplement (); }
158 set { throw GetMustImplement (); }
161 public static RequestCachePolicy DefaultCachePolicy
163 get { return defaultCachePolicy; }
165 throw GetMustImplement ();
169 public virtual WebHeaderCollection Headers {
170 get { throw GetMustImplement (); }
171 set { throw GetMustImplement (); }
175 public TokenImpersonationLevel ImpersonationLevel {
176 get { throw GetMustImplement (); }
177 set { throw GetMustImplement (); }
180 public virtual string Method {
181 get { throw GetMustImplement (); }
182 set { throw GetMustImplement (); }
185 public virtual bool PreAuthenticate {
186 get { throw GetMustImplement (); }
187 set { throw GetMustImplement (); }
190 public virtual IWebProxy Proxy {
191 get { throw GetMustImplement (); }
192 set { throw GetMustImplement (); }
195 public virtual Uri RequestUri {
196 get { throw GetMustImplement (); }
199 public virtual int Timeout {
200 get { throw GetMustImplement (); }
201 set { throw GetMustImplement (); }
204 public virtual bool UseDefaultCredentials
207 throw GetMustImplement ();
210 throw GetMustImplement ();
214 // volatile static IWebProxy proxy;
215 static readonly object lockobj = new object ();
217 public static IWebProxy DefaultWebProxy {
219 if (!isDefaultWebProxySet) {
221 if (defaultWebProxy == null)
222 defaultWebProxy = GetDefaultWebProxy ();
225 return defaultWebProxy;
228 /* MS documentation states that a null value would cause an ArgumentNullException
229 * but that's not the way it behaves:
230 * https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=304724
232 defaultWebProxy = value;
233 isDefaultWebProxySet = true;
237 [MonoTODO("Needs to respect Module, Proxy.AutoDetect, and Proxy.ScriptLocation config settings")]
238 static IWebProxy GetDefaultWebProxy ()
240 #if CONFIGURATION_DEP
241 DefaultProxySection sec = ConfigurationManager.GetSection ("system.net/defaultProxy") as DefaultProxySection;
245 return GetSystemWebProxy ();
247 ProxyElement pe = sec.Proxy;
249 if ((pe.UseSystemDefault != ProxyElement.UseSystemDefaultValues.False) && (pe.ProxyAddress == null))
250 p = (WebProxy) GetSystemWebProxy ();
254 if (pe.ProxyAddress != null)
255 p.Address = pe.ProxyAddress;
257 if (pe.BypassOnLocal != ProxyElement.BypassOnLocalValues.Unspecified)
258 p.BypassProxyOnLocal = (pe.BypassOnLocal == ProxyElement.BypassOnLocalValues.True);
260 foreach(BypassElement elem in sec.BypassList)
261 p.BypassArrayList.Add(elem.Address);
265 return GetSystemWebProxy ();
271 public virtual void Abort()
273 throw GetMustImplement ();
276 public virtual IAsyncResult BeginGetRequestStream (AsyncCallback callback, object state)
278 throw GetMustImplement ();
281 public virtual IAsyncResult BeginGetResponse (AsyncCallback callback, object state)
283 throw GetMustImplement ();
286 public static WebRequest Create (string requestUriString)
288 if (requestUriString == null)
289 throw new ArgumentNullException ("requestUriString");
290 return Create (new Uri (requestUriString));
293 public static WebRequest Create (Uri requestUri)
295 if (requestUri == null)
296 throw new ArgumentNullException ("requestUri");
297 return GetCreator (requestUri.AbsoluteUri).Create (requestUri);
300 public static WebRequest CreateDefault (Uri requestUri)
302 if (requestUri == null)
303 throw new ArgumentNullException ("requestUri");
304 return GetCreator (requestUri.Scheme).Create (requestUri);
307 public virtual Stream EndGetRequestStream (IAsyncResult asyncResult)
309 throw GetMustImplement ();
312 public virtual WebResponse EndGetResponse (IAsyncResult asyncResult)
314 throw GetMustImplement ();
317 public virtual Stream GetRequestStream()
319 throw GetMustImplement ();
322 public virtual WebResponse GetResponse()
324 throw GetMustImplement ();
327 [MonoTODO("Look in other places for proxy config info")]
328 public static IWebProxy GetSystemWebProxy ()
331 int iProxyEnable = (int)Microsoft.Win32.Registry.GetValue ("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", "ProxyEnable", 0);
333 if (iProxyEnable > 0) {
334 string strHttpProxy = "";
335 string[] bypassList = null;
336 bool bBypassOnLocal = false;
338 string strProxyServer = (string)Microsoft.Win32.Registry.GetValue ("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", "ProxyServer", null);
339 string strProxyOverrride = (string)Microsoft.Win32.Registry.GetValue ("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", "ProxyOverride", null);
341 if (strProxyServer.Contains ("=")) {
342 foreach (string strEntry in strProxyServer.Split (new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
343 if (strEntry.StartsWith ("http=")) {
344 strHttpProxy = strEntry.Substring (5);
347 } else strHttpProxy = strProxyServer;
349 if (strProxyOverrride != null)
350 bypassList = strProxyOverrride.Split (new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
352 ArrayList al = new ArrayList ();
354 foreach (string str in bypassList) {
355 if (str != "<local>")al.Add (str);
356 else bBypassOnLocal = true;
359 return new WebProxy (strHttpProxy, bBypassOnLocal, al.ToArray (typeof(string)) as string[]);
362 string address = Environment.GetEnvironmentVariable ("http_proxy");
365 address = Environment.GetEnvironmentVariable ("HTTP_PROXY");
367 if (address != null) {
369 if (!address.StartsWith ("http://"))
370 address = "http://" + address;
372 Uri uri = new Uri (address);
375 if (IPAddress.TryParse (uri.Host, out ip)) {
376 if (IPAddress.Any.Equals (ip)) {
377 UriBuilder builder = new UriBuilder (uri);
378 builder.Host = "127.0.0.1";
380 } else if (IPAddress.IPv6Any.Equals (ip)) {
381 UriBuilder builder = new UriBuilder (uri);
382 builder.Host = "[::1]";
387 bool bBypassOnLocal = false;
388 string[] bypassList = null;
389 ArrayList al = new ArrayList ();
390 string bypass = Environment.GetEnvironmentVariable ("no_proxy");
393 bypass = Environment.GetEnvironmentVariable ("NO_PROXY");
396 bypassList = bypass.Split (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
398 foreach (string str in bypassList) {
399 if (str != "*.local")al.Add (str);
400 else bBypassOnLocal = true;
403 return new WebProxy (uri, bBypassOnLocal, al.ToArray (typeof(string)) as string[]);
404 } catch (UriFormatException) {
409 if (cfGetDefaultProxy != null)
410 return (IWebProxy) cfGetDefaultProxy.Invoke (null, null);
412 return new WebProxy ();
415 void ISerializable.GetObjectData (SerializationInfo serializationInfo, StreamingContext streamingContext)
417 throw new NotSupportedException ();
420 protected virtual void GetObjectData (SerializationInfo serializationInfo, StreamingContext streamingContext)
422 throw GetMustImplement ();
425 public static bool RegisterPrefix (string prefix, IWebRequestCreate creator)
428 throw new ArgumentNullException ("prefix");
430 throw new ArgumentNullException ("creator");
432 lock (prefixes.SyncRoot) {
433 string lowerCasePrefix = prefix.ToLower (CultureInfo.InvariantCulture);
434 if (prefixes.Contains (lowerCasePrefix))
436 prefixes.Add (lowerCasePrefix, creator);
441 private static IWebRequestCreate GetCreator (string prefix)
443 int longestPrefix = -1;
444 IWebRequestCreate creator = null;
446 prefix = prefix.ToLower (CultureInfo.InvariantCulture);
448 IDictionaryEnumerator e = prefixes.GetEnumerator ();
449 while (e.MoveNext ()) {
450 string key = e.Key as string;
452 if (key.Length <= longestPrefix)
455 if (!prefix.StartsWith (key))
458 longestPrefix = key.Length;
459 creator = (IWebRequestCreate) e.Value;
463 throw new NotSupportedException (prefix);
468 internal static bool IsWindows ()
470 return Environment.GetEnvironmentVariable ("windir") != null;
473 internal static void ClearPrefixes ()
478 internal static void RemovePrefix (string prefix)
480 prefixes.Remove (prefix);
483 internal static void AddPrefix (string prefix, string typeName)
485 Type type = Type.GetType (typeName);
487 throw new ConfigurationException (String.Format ("Type {0} not found", typeName));
488 AddPrefix (prefix, type);
491 internal static void AddPrefix (string prefix, Type type)
493 object o = Activator.CreateInstance (type, true);
494 prefixes [prefix] = o;
498 public virtual Task<Stream> GetRequestStreamAsync ()
500 return Task<Stream>.Factory.FromAsync (BeginGetRequestStream, EndGetRequestStream, null);
503 public virtual Task<WebResponse> GetResponseAsync ()
505 return Task<WebResponse>.Factory.FromAsync (BeginGetResponse, EndGetResponse, null);