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;
72 IWebRequestCreate http = new HttpRequestCreator ();
73 RegisterPrefix ("http", http);
74 RegisterPrefix ("https", http);
76 RegisterPrefix ("file", new FileWebRequestCreator ());
77 RegisterPrefix ("ftp", new FtpRequestCreator ());
80 defaultCachePolicy = new HttpRequestCachePolicy (HttpRequestCacheLevel.NoCacheNoStore);
82 object cfg = ConfigurationManager.GetSection ("system.net/webRequestModules");
83 WebRequestModulesSection s = cfg as WebRequestModulesSection;
85 foreach (WebRequestModuleElement el in
87 AddPrefix (el.Prefix, el.Type);
91 ConfigurationSettings.GetConfig ("system.net/webRequestModules");
95 protected WebRequest ()
99 protected WebRequest (SerializationInfo serializationInfo, StreamingContext streamingContext)
103 static Exception GetMustImplement ()
105 return new NotImplementedException ("This method must be implemented in derived classes");
110 private AuthenticationLevel authentication_level = AuthenticationLevel.MutualAuthRequested;
112 public AuthenticationLevel AuthenticationLevel
115 return(authentication_level);
118 authentication_level = value;
122 [MonoTODO ("Implement the caching system. Currently always returns a policy with the NoCacheNoStore level")]
123 public virtual RequestCachePolicy CachePolicy
125 get { return DefaultCachePolicy; }
130 public virtual string ConnectionGroupName {
131 get { throw GetMustImplement (); }
132 set { throw GetMustImplement (); }
135 public virtual long ContentLength {
136 get { throw GetMustImplement (); }
137 set { throw GetMustImplement (); }
140 public virtual string ContentType {
141 get { throw GetMustImplement (); }
142 set { throw GetMustImplement (); }
145 public virtual ICredentials Credentials {
146 get { throw GetMustImplement (); }
147 set { throw GetMustImplement (); }
150 public static RequestCachePolicy DefaultCachePolicy
152 get { return defaultCachePolicy; }
154 throw GetMustImplement ();
158 public virtual WebHeaderCollection Headers {
159 get { throw GetMustImplement (); }
160 set { throw GetMustImplement (); }
164 public TokenImpersonationLevel ImpersonationLevel {
165 get { throw GetMustImplement (); }
166 set { throw GetMustImplement (); }
169 public virtual string Method {
170 get { throw GetMustImplement (); }
171 set { throw GetMustImplement (); }
174 public virtual bool PreAuthenticate {
175 get { throw GetMustImplement (); }
176 set { throw GetMustImplement (); }
179 public virtual IWebProxy Proxy {
180 get { throw GetMustImplement (); }
181 set { throw GetMustImplement (); }
184 public virtual Uri RequestUri {
185 get { throw GetMustImplement (); }
188 public virtual int Timeout {
189 get { throw GetMustImplement (); }
190 set { throw GetMustImplement (); }
193 public virtual bool UseDefaultCredentials
196 throw GetMustImplement ();
199 throw GetMustImplement ();
203 // volatile static IWebProxy proxy;
204 static readonly object lockobj = new object ();
206 public static IWebProxy DefaultWebProxy {
208 if (!isDefaultWebProxySet) {
210 if (defaultWebProxy == null)
211 defaultWebProxy = GetDefaultWebProxy ();
214 return defaultWebProxy;
217 /* MS documentation states that a null value would cause an ArgumentNullException
218 * but that's not the way it behaves:
219 * https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=304724
221 defaultWebProxy = value;
222 isDefaultWebProxySet = true;
226 [MonoTODO("Needs to respect Module, Proxy.AutoDetect, and Proxy.ScriptLocation config settings")]
227 static IWebProxy GetDefaultWebProxy ()
229 #if CONFIGURATION_DEP
230 DefaultProxySection sec = ConfigurationManager.GetSection ("system.net/defaultProxy") as DefaultProxySection;
234 return GetSystemWebProxy ();
236 ProxyElement pe = sec.Proxy;
238 if ((pe.UseSystemDefault != ProxyElement.UseSystemDefaultValues.False) && (pe.ProxyAddress == null)) {
239 IWebProxy proxy = GetSystemWebProxy ();
241 if (!(proxy is WebProxy))
244 p = (WebProxy) proxy;
248 if (pe.ProxyAddress != null)
249 p.Address = pe.ProxyAddress;
251 if (pe.BypassOnLocal != ProxyElement.BypassOnLocalValues.Unspecified)
252 p.BypassProxyOnLocal = (pe.BypassOnLocal == ProxyElement.BypassOnLocalValues.True);
254 foreach(BypassElement elem in sec.BypassList)
255 p.BypassArrayList.Add(elem.Address);
259 return GetSystemWebProxy ();
265 public virtual void Abort()
267 throw GetMustImplement ();
270 public virtual IAsyncResult BeginGetRequestStream (AsyncCallback callback, object state)
272 throw GetMustImplement ();
275 public virtual IAsyncResult BeginGetResponse (AsyncCallback callback, object state)
277 throw GetMustImplement ();
280 public static WebRequest Create (string requestUriString)
282 if (requestUriString == null)
283 throw new ArgumentNullException ("requestUriString");
284 return Create (new Uri (requestUriString));
287 public static WebRequest Create (Uri requestUri)
289 if (requestUri == null)
290 throw new ArgumentNullException ("requestUri");
291 return GetCreator (requestUri.AbsoluteUri).Create (requestUri);
294 public static WebRequest CreateDefault (Uri requestUri)
296 if (requestUri == null)
297 throw new ArgumentNullException ("requestUri");
298 return GetCreator (requestUri.Scheme).Create (requestUri);
300 #if NET_4_5 || MOBILE
301 [MonoTODO ("for portable library support")]
302 public static HttpWebRequest CreateHttp (string requestUriString)
304 throw new NotImplementedException ();
307 [MonoTODO ("for portable library support")]
308 public static HttpWebRequest CreateHttp (Uri requestUri)
310 throw new NotImplementedException ();
313 public virtual Stream EndGetRequestStream (IAsyncResult asyncResult)
315 throw GetMustImplement ();
318 public virtual WebResponse EndGetResponse (IAsyncResult asyncResult)
320 throw GetMustImplement ();
323 public virtual Stream GetRequestStream()
325 throw GetMustImplement ();
328 public virtual WebResponse GetResponse()
330 throw GetMustImplement ();
333 [MonoTODO("Look in other places for proxy config info")]
334 public static IWebProxy GetSystemWebProxy ()
338 int iProxyEnable = (int)Microsoft.Win32.Registry.GetValue ("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", "ProxyEnable", 0);
340 if (iProxyEnable > 0) {
341 string strHttpProxy = "";
342 bool bBypassOnLocal = false;
343 ArrayList al = new ArrayList ();
345 string strProxyServer = (string)Microsoft.Win32.Registry.GetValue ("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", "ProxyServer", null);
346 string strProxyOverrride = (string)Microsoft.Win32.Registry.GetValue ("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", "ProxyOverride", null);
348 if (strProxyServer.Contains ("=")) {
349 foreach (string strEntry in strProxyServer.Split (new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
350 if (strEntry.StartsWith ("http=")) {
351 strHttpProxy = strEntry.Substring (5);
354 } else strHttpProxy = strProxyServer;
356 if (strProxyOverrride != null) {
357 string[] bypassList = strProxyOverrride.Split (new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
359 foreach (string str in bypassList) {
360 if (str != "<local>")
363 bBypassOnLocal = true;
367 return new WebProxy (strHttpProxy, bBypassOnLocal, al.ToArray (typeof(string)) as string[]);
371 if (Platform.IsMacOS)
372 return CFNetwork.GetDefaultProxy ();
374 string address = Environment.GetEnvironmentVariable ("http_proxy");
377 address = Environment.GetEnvironmentVariable ("HTTP_PROXY");
379 if (address != null) {
381 if (!address.StartsWith ("http://"))
382 address = "http://" + address;
384 Uri uri = new Uri (address);
387 if (IPAddress.TryParse (uri.Host, out ip)) {
388 if (IPAddress.Any.Equals (ip)) {
389 UriBuilder builder = new UriBuilder (uri);
390 builder.Host = "127.0.0.1";
392 } else if (IPAddress.IPv6Any.Equals (ip)) {
393 UriBuilder builder = new UriBuilder (uri);
394 builder.Host = "[::1]";
399 bool bBypassOnLocal = false;
400 ArrayList al = new ArrayList ();
401 string bypass = Environment.GetEnvironmentVariable ("no_proxy");
404 bypass = Environment.GetEnvironmentVariable ("NO_PROXY");
406 if (bypass != null) {
407 string[] bypassList = bypass.Split (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
409 foreach (string str in bypassList) {
410 if (str != "*.local")
413 bBypassOnLocal = true;
417 return new WebProxy (uri, bBypassOnLocal, al.ToArray (typeof(string)) as string[]);
418 } catch (UriFormatException) {
425 return new WebProxy ();
428 void ISerializable.GetObjectData (SerializationInfo serializationInfo, StreamingContext streamingContext)
430 throw new NotSupportedException ();
433 protected virtual void GetObjectData (SerializationInfo serializationInfo, StreamingContext streamingContext)
435 throw GetMustImplement ();
438 public static bool RegisterPrefix (string prefix, IWebRequestCreate creator)
441 throw new ArgumentNullException ("prefix");
443 throw new ArgumentNullException ("creator");
445 lock (prefixes.SyncRoot) {
446 string lowerCasePrefix = prefix.ToLower (CultureInfo.InvariantCulture);
447 if (prefixes.Contains (lowerCasePrefix))
449 prefixes.Add (lowerCasePrefix, creator);
454 private static IWebRequestCreate GetCreator (string prefix)
456 int longestPrefix = -1;
457 IWebRequestCreate creator = null;
459 prefix = prefix.ToLower (CultureInfo.InvariantCulture);
461 IDictionaryEnumerator e = prefixes.GetEnumerator ();
462 while (e.MoveNext ()) {
463 string key = e.Key as string;
465 if (key.Length <= longestPrefix)
468 if (!prefix.StartsWith (key))
471 longestPrefix = key.Length;
472 creator = (IWebRequestCreate) e.Value;
476 throw new NotSupportedException (prefix);
481 internal static bool IsWindows ()
483 return (int) Environment.OSVersion.Platform < 4;
486 internal static void ClearPrefixes ()
491 internal static void RemovePrefix (string prefix)
493 prefixes.Remove (prefix);
496 internal static void AddPrefix (string prefix, string typeName)
498 Type type = Type.GetType (typeName);
500 throw new ConfigurationException (String.Format ("Type {0} not found", typeName));
501 AddPrefix (prefix, type);
504 internal static void AddPrefix (string prefix, Type type)
506 object o = Activator.CreateInstance (type, true);
507 prefixes [prefix] = o;
511 public virtual Task<Stream> GetRequestStreamAsync ()
513 return Task<Stream>.Factory.FromAsync (BeginGetRequestStream, EndGetRequestStream, null);
516 public virtual Task<WebResponse> GetResponseAsync ()
518 return Task<WebResponse>.Factory.FromAsync (BeginGetResponse, EndGetResponse, null);