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;
42 using System.Threading.Tasks;
45 using ConfigurationException = System.ArgumentException;
47 namespace System.Net.Configuration {
55 public abstract class WebRequest : MarshalByRefObject, ISerializable {
56 static HybridDictionary prefixes = new HybridDictionary ();
57 static bool isDefaultWebProxySet;
58 static IWebProxy defaultWebProxy;
59 static RequestCachePolicy defaultCachePolicy;
64 IWebRequestCreate http = new HttpRequestCreator ();
65 RegisterPrefix ("http", http);
66 RegisterPrefix ("https", http);
67 RegisterPrefix ("file", new FileWebRequestCreator ());
68 RegisterPrefix ("ftp", new FtpRequestCreator ());
71 object cfg = ConfigurationManager.GetSection ("system.net/webRequestModules");
72 WebRequestModulesSection s = cfg as WebRequestModulesSection;
74 foreach (WebRequestModuleElement el in
76 AddPrefix (el.Prefix, el.Type);
80 ConfigurationSettings.GetConfig ("system.net/webRequestModules");
84 protected WebRequest ()
88 protected WebRequest (SerializationInfo serializationInfo, StreamingContext streamingContext)
92 static Exception GetMustImplement ()
94 return new NotImplementedException ("This method must be implemented in derived classes");
99 private AuthenticationLevel authentication_level = AuthenticationLevel.MutualAuthRequested;
101 public AuthenticationLevel AuthenticationLevel
104 return(authentication_level);
107 authentication_level = value;
111 public virtual string ConnectionGroupName {
112 get { throw GetMustImplement (); }
113 set { throw GetMustImplement (); }
116 public virtual long ContentLength {
117 get { throw GetMustImplement (); }
118 set { throw GetMustImplement (); }
121 public virtual string ContentType {
122 get { throw GetMustImplement (); }
123 set { throw GetMustImplement (); }
126 public virtual ICredentials Credentials {
127 get { throw GetMustImplement (); }
128 set { throw GetMustImplement (); }
131 [MonoTODO ("Implement the caching system. Currently always returns a policy with the NoCacheNoStore level")]
132 public virtual RequestCachePolicy CachePolicy
134 get { return DefaultCachePolicy; }
139 public static RequestCachePolicy DefaultCachePolicy {
141 return defaultCachePolicy ?? (defaultCachePolicy = new HttpRequestCachePolicy (HttpRequestCacheLevel.NoCacheNoStore));
144 throw GetMustImplement ();
148 public virtual WebHeaderCollection Headers {
149 get { throw GetMustImplement (); }
150 set { throw GetMustImplement (); }
154 public virtual string Method {
155 get { throw GetMustImplement (); }
156 set { throw GetMustImplement (); }
159 public virtual bool PreAuthenticate {
160 get { throw GetMustImplement (); }
161 set { throw GetMustImplement (); }
164 public virtual IWebProxy Proxy {
165 get { throw GetMustImplement (); }
166 set { throw GetMustImplement (); }
169 public virtual Uri RequestUri {
170 get { throw GetMustImplement (); }
173 public virtual int Timeout {
174 get { throw GetMustImplement (); }
175 set { throw GetMustImplement (); }
178 public virtual bool UseDefaultCredentials
181 throw GetMustImplement ();
184 throw GetMustImplement ();
188 public TokenImpersonationLevel ImpersonationLevel { get; set; }
190 // volatile static IWebProxy proxy;
191 static readonly object lockobj = new object ();
193 public static IWebProxy DefaultWebProxy {
195 if (!isDefaultWebProxySet) {
197 if (defaultWebProxy == null)
198 defaultWebProxy = GetDefaultWebProxy ();
201 return defaultWebProxy;
204 /* MS documentation states that a null value would cause an ArgumentNullException
205 * but that's not the way it behaves:
206 * https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=304724
208 defaultWebProxy = value;
209 isDefaultWebProxySet = true;
213 internal static IWebProxy InternalDefaultWebProxy {
215 return DefaultWebProxy;
220 [MonoTODO("Needs to respect Module, Proxy.AutoDetect, and Proxy.ScriptLocation config settings")]
221 static IWebProxy GetDefaultWebProxy ()
223 #if CONFIGURATION_DEP
224 DefaultProxySection sec = ConfigurationManager.GetSection ("system.net/defaultProxy") as DefaultProxySection;
228 return GetSystemWebProxy ();
230 ProxyElement pe = sec.Proxy;
232 if ((pe.UseSystemDefault != ProxyElement.UseSystemDefaultValues.False) && (pe.ProxyAddress == null)) {
233 IWebProxy proxy = GetSystemWebProxy ();
235 if (!(proxy is WebProxy))
238 p = (WebProxy) proxy;
242 if (pe.ProxyAddress != null)
243 p.Address = pe.ProxyAddress;
245 if (pe.BypassOnLocal != ProxyElement.BypassOnLocalValues.Unspecified)
246 p.BypassProxyOnLocal = (pe.BypassOnLocal == ProxyElement.BypassOnLocalValues.True);
248 foreach(BypassElement elem in sec.BypassList)
249 p.BypassArrayList.Add(elem.Address);
253 return GetSystemWebProxy ();
259 public virtual void Abort()
261 throw GetMustImplement ();
264 public virtual IAsyncResult BeginGetRequestStream (AsyncCallback callback, object state)
266 throw GetMustImplement ();
269 public virtual IAsyncResult BeginGetResponse (AsyncCallback callback, object state)
271 throw GetMustImplement ();
274 public static WebRequest Create (string requestUriString)
276 if (requestUriString == null)
277 throw new ArgumentNullException ("requestUriString");
278 return Create (new Uri (requestUriString));
281 public static WebRequest Create (Uri requestUri)
283 if (requestUri == null)
284 throw new ArgumentNullException ("requestUri");
285 return GetCreator (requestUri.AbsoluteUri).Create (requestUri);
288 public static WebRequest CreateDefault (Uri requestUri)
290 if (requestUri == null)
291 throw new ArgumentNullException ("requestUri");
292 return GetCreator (requestUri.Scheme).Create (requestUri);
294 static HttpWebRequest SharedCreateHttp (Uri uri)
296 if (uri.Scheme != "http" && uri.Scheme != "https")
297 throw new NotSupportedException ("The uri should start with http or https");
299 return new HttpWebRequest (uri);
302 public static HttpWebRequest CreateHttp (string requestUriString)
304 if (requestUriString == null)
305 throw new ArgumentNullException ("requestUriString");
306 return SharedCreateHttp (new Uri (requestUriString));
309 public static HttpWebRequest CreateHttp (Uri requestUri)
311 if (requestUri == null)
312 throw new ArgumentNullException ("requestUri");
313 return SharedCreateHttp (requestUri);
315 public virtual Stream EndGetRequestStream (IAsyncResult asyncResult)
317 throw GetMustImplement ();
320 public virtual WebResponse EndGetResponse (IAsyncResult asyncResult)
322 throw GetMustImplement ();
325 public virtual Stream GetRequestStream()
327 throw GetMustImplement ();
330 public virtual WebResponse GetResponse()
332 throw GetMustImplement ();
335 [MonoTODO("Look in other places for proxy config info")]
336 public static IWebProxy GetSystemWebProxy ()
339 return CFNetwork.GetDefaultProxy ();
342 // Return the system web proxy. This only works for ICS+.
343 var androidProxy = AndroidPlatform.GetDefaultProxy ();
344 if (androidProxy != null)
349 int iProxyEnable = (int)Microsoft.Win32.Registry.GetValue ("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", "ProxyEnable", 0);
351 if (iProxyEnable > 0) {
352 string strHttpProxy = "";
353 bool bBypassOnLocal = false;
354 ArrayList al = new ArrayList ();
356 string strProxyServer = (string)Microsoft.Win32.Registry.GetValue ("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", "ProxyServer", null);
357 string strProxyOverrride = (string)Microsoft.Win32.Registry.GetValue ("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", "ProxyOverride", null);
359 if (strProxyServer.Contains ("=")) {
360 foreach (string strEntry in strProxyServer.Split (new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
361 if (strEntry.StartsWith ("http=")) {
362 strHttpProxy = strEntry.Substring (5);
365 } else strHttpProxy = strProxyServer;
367 if (strProxyOverrride != null) {
368 string[] bypassList = strProxyOverrride.Split (new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
370 foreach (string str in bypassList) {
371 if (str != "<local>")
374 bBypassOnLocal = true;
378 return new WebProxy (strHttpProxy, bBypassOnLocal, al.ToArray (typeof(string)) as string[]);
382 if (Platform.IsMacOS)
383 return CFNetwork.GetDefaultProxy ();
385 string address = Environment.GetEnvironmentVariable ("http_proxy");
388 address = Environment.GetEnvironmentVariable ("HTTP_PROXY");
390 if (address != null) {
392 if (!address.StartsWith ("http://"))
393 address = "http://" + address;
395 Uri uri = new Uri (address);
398 if (IPAddress.TryParse (uri.Host, out ip)) {
399 if (IPAddress.Any.Equals (ip)) {
400 UriBuilder builder = new UriBuilder (uri);
401 builder.Host = "127.0.0.1";
403 } else if (IPAddress.IPv6Any.Equals (ip)) {
404 UriBuilder builder = new UriBuilder (uri);
405 builder.Host = "[::1]";
410 bool bBypassOnLocal = false;
411 ArrayList al = new ArrayList ();
412 string bypass = Environment.GetEnvironmentVariable ("no_proxy");
415 bypass = Environment.GetEnvironmentVariable ("NO_PROXY");
417 if (bypass != null) {
418 string[] bypassList = bypass.Split (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
420 foreach (string str in bypassList) {
421 if (str != "*.local")
424 bBypassOnLocal = true;
428 return new WebProxy (uri, bBypassOnLocal, al.ToArray (typeof(string)) as string[]);
429 } catch (UriFormatException) {
436 return new WebProxy ();
440 void ISerializable.GetObjectData (SerializationInfo serializationInfo, StreamingContext streamingContext)
442 throw new NotSupportedException ();
445 protected virtual void GetObjectData (SerializationInfo serializationInfo, StreamingContext streamingContext)
447 throw GetMustImplement ();
450 public static bool RegisterPrefix (string prefix, IWebRequestCreate creator)
453 throw new ArgumentNullException ("prefix");
455 throw new ArgumentNullException ("creator");
457 lock (prefixes.SyncRoot) {
458 string lowerCasePrefix = prefix.ToLower (CultureInfo.InvariantCulture);
459 if (prefixes.Contains (lowerCasePrefix))
461 prefixes.Add (lowerCasePrefix, creator);
466 private static IWebRequestCreate GetCreator (string prefix)
468 int longestPrefix = -1;
469 IWebRequestCreate creator = null;
471 prefix = prefix.ToLower (CultureInfo.InvariantCulture);
473 IDictionaryEnumerator e = prefixes.GetEnumerator ();
474 while (e.MoveNext ()) {
475 string key = e.Key as string;
477 if (key.Length <= longestPrefix)
480 if (!prefix.StartsWith (key))
483 longestPrefix = key.Length;
484 creator = (IWebRequestCreate) e.Value;
488 throw new NotSupportedException (prefix);
493 internal static bool IsWindows ()
495 return (int) Environment.OSVersion.Platform < 4;
498 internal static void ClearPrefixes ()
503 internal static void RemovePrefix (string prefix)
505 prefixes.Remove (prefix);
508 internal static void AddPrefix (string prefix, string typeName)
510 Type type = Type.GetType (typeName);
512 throw new ConfigurationException (String.Format ("Type {0} not found", typeName));
513 AddPrefix (prefix, type);
516 internal static void AddPrefix (string prefix, Type type)
518 object o = Activator.CreateInstance (type, true);
519 prefixes [prefix] = o;
522 public virtual Task<Stream> GetRequestStreamAsync ()
524 return Task<Stream>.Factory.FromAsync (BeginGetRequestStream, EndGetRequestStream, null);
527 public virtual Task<WebResponse> GetResponseAsync ()
529 return Task<WebResponse>.Factory.FromAsync (BeginGetResponse, EndGetResponse, null);