1 //------------------------------------------------------------------------------
2 // <copyright file="WebRequest.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 //------------------------------------------------------------------------------
8 using System.Collections;
9 using System.Collections.Generic;
10 using System.Configuration;
11 using System.Diagnostics.CodeAnalysis;
12 using System.Diagnostics.Contracts;
13 using System.Diagnostics.Tracing;
14 using System.Globalization;
16 using System.Net.Cache;
17 using System.Net.Configuration;
18 using System.Reflection;
19 using System.Runtime.Serialization;
20 using System.Security.Permissions;
21 using System.Security.Principal;
22 using System.Threading;
23 using System.Threading.Tasks;
24 using System.Net.Security;
25 using System.ComponentModel;
26 using System.Security;
28 // WebRequest - the base class of all Web resource/protocol objects. Provides
29 // common methods, data and proprties for making the top level request
33 /// <para>A request to a Uniform Resource Identifier (Uri). This
34 /// is an abstract class.</para>
37 public abstract class WebRequest : MarshalByRefObject, ISerializable
39 #if FEATURE_PAL // ROTORTODO - after speed ups (like real JIT and GC) remove this one
41 internal const int DefaultTimeout = 100000 * 10;
43 internal const int DefaultTimeout = 100000 * 5;
46 internal const int DefaultTimeout = 100000; // default timeout is 100 seconds (ASP .NET is 90 seconds)
48 private static volatile ArrayList s_PrefixList;
49 private static Object s_InternalSyncObject;
50 private static TimerThread.Queue s_DefaultTimerQueue = TimerThread.CreateQueue(DefaultTimeout);
53 private AuthenticationLevel m_AuthenticationLevel;
54 private TokenImpersonationLevel m_ImpersonationLevel;
56 private RequestCachePolicy m_CachePolicy;
57 private RequestCacheProtocol m_CacheProtocol;
58 private RequestCacheBinding m_CacheBinding;
60 #region designer support for System.Windows.dll
61 internal class DesignerWebRequestCreate : IWebRequestCreate
63 public WebRequest Create(Uri uri)
65 return WebRequest.Create(uri);
68 private static DesignerWebRequestCreate webRequestCreate = new DesignerWebRequestCreate();
69 //introduced for supporting design-time loading of System.Windows.dll
70 [Obsolete("This API supports the .NET Framework infrastructure and is not intended to be used directly from your code.", true)]
71 [EditorBrowsable(EditorBrowsableState.Never)]
72 public virtual IWebRequestCreate CreatorInstance { get { return webRequestCreate; } }
74 //introduced for supporting design-time loading of System.Windows.dll
75 [Obsolete("This API supports the .NET Framework infrastructure and is not intended to be used directly from your code.", true)]
76 [EditorBrowsable(EditorBrowsableState.Never)]
77 public static void RegisterPortableWebRequestCreator(IWebRequestCreate creator) { }
80 private static Object InternalSyncObject {
82 if (s_InternalSyncObject == null) {
83 Object o = new Object();
84 Interlocked.CompareExchange(ref s_InternalSyncObject, o, null);
86 return s_InternalSyncObject;
90 internal static TimerThread.Queue DefaultTimerQueue {
92 return s_DefaultTimerQueue;
98 Create - Create a WebRequest.
100 This is the main creation routine. We take a Uri object, look
101 up the Uri in the prefix match table, and invoke the appropriate
102 handler to create the object. We also have a parameter that
103 tells us whether or not to use the whole Uri or just the
104 scheme portion of it.
108 RequestUri - Uri object for request.
109 UseUriBase - True if we're only to look at the scheme
114 Newly created WebRequest.
117 private static WebRequest Create(Uri requestUri, bool useUriBase) {
118 if(Logging.On)Logging.Enter(Logging.Web, "WebRequest", "Create", requestUri.ToString());
121 WebRequestPrefixElement Current = null;
126 LookupUri = requestUri.AbsoluteUri;
131 // schemes are registered as <schemeName>":", so add the separator
132 // to the string returned from the Uri object
135 LookupUri = requestUri.Scheme + ':';
138 int LookupLength = LookupUri.Length;
140 // Copy the prefix list so that if it is updated it will
141 // not affect us on this thread.
143 ArrayList prefixList = PrefixList;
145 // Look for the longest matching prefix.
147 // Walk down the list of prefixes. The prefixes are kept longest
148 // first. When we find a prefix that is shorter or the same size
149 // as this Uri, we'll do a compare to see if they match. If they
150 // do we'll break out of the loop and call the creator.
152 for (int i = 0; i < prefixList.Count; i++) {
153 Current = (WebRequestPrefixElement)prefixList[i];
156 // See if this prefix is short enough.
159 if (LookupLength >= Current.Prefix.Length) {
162 // It is. See if these match.
165 if (String.Compare(Current.Prefix,
169 Current.Prefix.Length,
170 StringComparison.OrdinalIgnoreCase ) == 0) {
173 // These match. Remember that we found it and break
183 WebRequest webRequest = null;
188 // We found a match, so just call the creator and return what it
192 webRequest = Current.Creator.Create(requestUri);
193 if(Logging.On)Logging.Exit(Logging.Web, "WebRequest", "Create", webRequest);
197 if(Logging.On)Logging.Exit(Logging.Web, "WebRequest", "Create", null);
200 // Otherwise no match, throw an exception.
203 throw new NotSupportedException(SR.GetString(SR.net_unknown_prefix));
208 Create - Create a WebRequest.
210 An overloaded utility version of the real Create that takes a
211 string instead of an Uri object.
216 RequestString - Uri string to create.
220 Newly created WebRequest.
225 /// Creates a new <see cref='System.Net.WebRequest'/>
227 /// the specified Uri scheme.
230 public static WebRequest Create(string requestUriString) {
231 if (requestUriString == null) {
232 throw new ArgumentNullException("requestUriString");
234 // In .NET FX v4.0, custom IWebRequestCreate implementations can
235 // cause this to return null. Consider tightening this in the future.
236 //Contract.Ensures(Contract.Result<WebRequest>() != null);
238 return Create(new Uri(requestUriString), false);
243 Create - Create a WebRequest.
245 Another overloaded version of the Create function that doesn't
246 take the UseUriBase parameter.
250 RequestUri - Uri object for request.
254 Newly created WebRequest.
259 /// Creates a new <see cref='System.Net.WebRequest'/> instance for the specified Uri scheme.
262 public static WebRequest Create(Uri requestUri) {
263 if (requestUri == null) {
264 throw new ArgumentNullException("requestUri");
266 // In .NET FX v4.0, custom IWebRequestCreate implementations can
267 // cause this to return null. Consider tightening this in the future.
268 //Contract.Ensures(Contract.Result<WebRequest>() != null);
270 return Create(requestUri, false);
275 CreateDefault - Create a default WebRequest.
277 This is the creation routine that creates a default WebRequest.
278 We take a Uri object and pass it to the base create routine,
279 setting the useUriBase parameter to true.
283 RequestUri - Uri object for request.
287 Newly created WebRequest.
290 /// <para>[To be supplied.]</para>
292 public static WebRequest CreateDefault(Uri requestUri) {
293 if (requestUri == null) {
294 throw new ArgumentNullException("requestUri");
296 // In .NET FX v4.0, custom IWebRequestCreate implementations can
297 // cause this to return null. Consider tightening this in the future.
298 //Contract.Ensures(Contract.Result<WebRequest>() != null);
300 return Create(requestUri, true);
304 public static HttpWebRequest CreateHttp(string requestUriString) {
305 if (requestUriString == null) {
306 throw new ArgumentNullException("requestUriString");
308 return CreateHttp(new Uri(requestUriString));
312 public static HttpWebRequest CreateHttp(Uri requestUri) {
313 if (requestUri == null) {
314 throw new ArgumentNullException("requestUri");
316 if ((requestUri.Scheme != Uri.UriSchemeHttp) && (requestUri.Scheme != Uri.UriSchemeHttps)) {
317 throw new NotSupportedException(SR.GetString(SR.net_unknown_prefix));
319 return (HttpWebRequest)CreateDefault(requestUri);
324 RegisterPrefix - Register an Uri prefix for creating WebRequests.
326 This function registers a prefix for creating WebRequests. When an
327 user wants to create a WebRequest, we scan a table looking for a
328 longest prefix match for the Uri they're passing. We then invoke
329 the sub creator for that prefix. This function puts entries in
332 We don't allow duplicate entries, so if there is a dup this call
337 Prefix - Represents Uri prefix being registered.
338 Creator - Interface for sub creator.
342 True if the registration worked, false otherwise.
347 /// Registers a <see cref='System.Net.WebRequest'/> descendent
348 /// for a specific Uniform Resource Identifier.
351 public static bool RegisterPrefix(string prefix, IWebRequestCreate creator) {
355 WebRequestPrefixElement Current;
357 if (prefix == null) {
358 throw new ArgumentNullException("prefix");
360 if (creator == null) {
361 throw new ArgumentNullException("creator");
364 ExceptionHelper.WebPermissionUnrestricted.Demand();
366 // Lock this object, then walk down PrefixList looking for a place to
367 // to insert this prefix.
369 lock(InternalSyncObject) {
371 // clone the object and update the clone thus
372 // allowing other threads to still read from it
375 ArrayList prefixList = (ArrayList)PrefixList.Clone();
377 // As AbsoluteUri is used later for Create, account for formating changes
378 // like Unicode escaping, default ports, etc.
380 if (Uri.TryCreate(prefix, UriKind.Absolute, out tempUri))
382 String cookedUri = tempUri.AbsoluteUri;
384 // Special case for when a partial host matching is requested, drop the added trailing slash
385 // IE: http://host could match host or host.domain
386 if (!prefix.EndsWith("/", StringComparison.Ordinal)
387 && tempUri.GetComponents(UriComponents.PathAndQuery | UriComponents.Fragment,
388 UriFormat.UriEscaped)
390 cookedUri = cookedUri.Substring(0, cookedUri.Length - 1);
397 // The prefix list is sorted with longest entries at the front. We
398 // walk down the list until we find a prefix shorter than this
399 // one, then we insert in front of it. Along the way we check
400 // equal length prefixes to make sure this isn't a dupe.
402 while (i < prefixList.Count) {
403 Current = (WebRequestPrefixElement)prefixList[i];
405 // See if the new one is longer than the one we're looking at.
407 if (prefix.Length > Current.Prefix.Length) {
408 // It is. Break out of the loop here.
412 // If these are of equal length, compare them.
414 if (prefix.Length == Current.Prefix.Length) {
415 // They're the same length.
416 if (String.Compare(Current.Prefix, prefix, StringComparison.OrdinalIgnoreCase) == 0) {
417 // ...and the strings are identical. This is an error.
426 // When we get here either i contains the index to insert at or
427 // we've had an error, in which case Error is true.
430 // No error, so insert.
433 new WebRequestPrefixElement(prefix, creator)
437 // no error, assign the clone to the static object, other
438 // threads using it will have copied the oriignal object already
440 PrefixList = prefixList;
447 public static bool UnregisterPrefix(string prefix) {
448 if (prefix == null) {
449 throw new ArgumentNullException("prefix");
451 ExceptionHelper.WebPermissionUnrestricted.Demand();
453 // Lock this object, then walk down PrefixList looking for a place to
454 // to insert this prefix.
456 lock(InternalSyncObject) {
458 // clone the object and update the clone thus
459 // allowing other threads to still read from it
462 ArrayList prefixList = (ArrayList) PrefixList.Clone();
465 WebRequestPrefixElement Current;
467 // The prefix list is sorted with longest entries at the front. We
468 // walk down the list until we find a prefix shorter than this
469 // one, then we insert in front of it. Along the way we check
470 // equal length prefixes to make sure this isn't a dupe.
471 while (i < prefixList.Count) {
472 Current = (WebRequestPrefixElement)prefixList[i];
474 // See if the new one is longer than the one we're looking at.
476 if (prefix.Length > Current.Prefix.Length) {
480 // If these are of equal length, compare them.
482 if (prefix.Length == Current.Prefix.Length) {
483 // They're the same length.
484 if (String.Compare(Current.Prefix, prefix, StringComparison.OrdinalIgnoreCase ) == 0) {
485 prefixList.RemoveAt(i);
486 PrefixList = prefixList;
501 PrefixList - Returns And Initialize our prefix list.
504 This is the method that initializes the prefix list. We create
505 an ArrayList for the PrefixList, then an HttpRequestCreator object,
506 and then we register the HTTP and HTTPS prefixes.
513 internal static ArrayList PrefixList {
517 // GetConfig() might use us, so we have a circular dependency issue,
518 // that causes us to nest here, we grab the lock, only
519 // if we haven't initialized.
521 if (s_PrefixList == null) {
523 lock (InternalSyncObject) {
524 if (s_PrefixList == null) {
525 GlobalLog.Print("WebRequest::Initialize(): calling ConfigurationManager.GetSection()");
526 s_PrefixList = WebRequestModulesSectionInternal.GetSection().WebRequestModules;
534 s_PrefixList = value;
542 /// Initializes a new instance of the <see cref='System.Net.WebRequest'/>
547 protected WebRequest()
550 // Defautl values are set as per V1.0 behavior
551 m_ImpersonationLevel = TokenImpersonationLevel.Delegation;
552 m_AuthenticationLevel= AuthenticationLevel.MutualAuthRequested;
556 // ISerializable constructor
559 /// <para>[To be supplied.]</para>
561 protected WebRequest(SerializationInfo serializationInfo, StreamingContext streamingContext) {
565 // ISerializable method
568 [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Justification = "System.dll is still using pre-v4 security model and needs this demand")]
569 [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.SerializationFormatter, SerializationFormatter=true)]
570 void ISerializable.GetObjectData(SerializationInfo serializationInfo, StreamingContext streamingContext)
572 GetObjectData(serializationInfo, streamingContext);
576 // FxCop: Provide a way for inherited classes to access base.GetObjectData in case they also implement ISerializable.
578 [SecurityPermission(SecurityAction.Demand, SerializationFormatter=true)]
579 protected virtual void GetObjectData(SerializationInfo serializationInfo, StreamingContext streamingContext)
583 // This is a shortcut that would set the default policy for HTTP/HTTPS.
584 // The default policy is overridden by any prefix-registered policy.
585 // Will demand permission for set{}
586 public static RequestCachePolicy DefaultCachePolicy {
588 return RequestCacheManager.GetBinding(string.Empty).Policy;
591 // This is a replacement of RequestCachePermission demand since we are not including the latest in the product.
592 ExceptionHelper.WebPermissionUnrestricted.Demand();
594 RequestCacheBinding binding = RequestCacheManager.GetBinding(string.Empty);
595 RequestCacheManager.SetBinding(string.Empty, new RequestCacheBinding(binding.Cache, binding.Validator, value));
601 public virtual RequestCachePolicy CachePolicy {
603 return m_CachePolicy;
607 // Delayed creation of CacheProtocol until caching is actually turned on.
608 InternalSetCachePolicy(value);
613 void InternalSetCachePolicy(RequestCachePolicy policy){
614 // Delayed creation of CacheProtocol until caching is actually turned on.
615 if (m_CacheBinding != null &&
616 m_CacheBinding.Cache != null &&
617 m_CacheBinding.Validator != null &&
618 CacheProtocol == null &&
620 policy.Level != RequestCacheLevel.BypassCache)
622 CacheProtocol = new RequestCacheProtocol(m_CacheBinding.Cache, m_CacheBinding.Validator.CreateValidator());
625 m_CachePolicy = policy;
630 /// <para>When overridden in a derived class, gets and
633 /// protocol method used in this request. Default value should be
636 public virtual string Method {
638 throw ExceptionHelper.PropertyNotImplementedException;
641 throw ExceptionHelper.PropertyNotImplementedException;
647 /// <para>When overridden in a derived class, gets a <see cref='Uri'/>
648 /// instance representing the resource associated with
649 /// the request.</para>
651 public virtual Uri RequestUri { // read-only
653 throw ExceptionHelper.PropertyNotImplementedException;
658 // This is a group of connections that may need to be used for
659 // grouping connecitons.
663 public virtual string ConnectionGroupName {
665 throw ExceptionHelper.PropertyNotImplementedException;
668 throw ExceptionHelper.PropertyNotImplementedException;
675 Headers - Gets any request specific headers associated
676 with this request, this is simply a name/value pair collection
680 Returns: This property returns WebHeaderCollection.
687 /// <para>When overridden in a derived class,
689 /// a collection of header name-value pairs associated with this
692 public virtual WebHeaderCollection Headers {
694 Contract.Ensures(Contract.Result<WebHeaderCollection>() != null);
695 throw ExceptionHelper.PropertyNotImplementedException;
698 throw ExceptionHelper.PropertyNotImplementedException;
705 /// overridden in a derived class, gets
708 /// content length of request data being sent.</para>
710 public virtual long ContentLength {
712 throw ExceptionHelper.PropertyNotImplementedException;
715 throw ExceptionHelper.PropertyNotImplementedException;
721 /// overridden in a derived class, gets
724 /// the content type of the request data being sent.</para>
726 public virtual string ContentType {
728 throw ExceptionHelper.PropertyNotImplementedException;
731 throw ExceptionHelper.PropertyNotImplementedException;
736 /// <para>When overridden in a derived class, gets and sets the network
737 /// credentials used for authentication to this Uri.</para>
739 public virtual ICredentials Credentials {
741 throw ExceptionHelper.PropertyNotImplementedException;
744 throw ExceptionHelper.PropertyNotImplementedException;
749 /// <para>Sets Credentials to CredentialCache.DefaultCredentials</para>
751 public virtual bool UseDefaultCredentials {
753 throw ExceptionHelper.PropertyNotImplementedException;
756 throw ExceptionHelper.PropertyNotImplementedException;
761 /// <para>When overridden in a derived class,
762 /// gets and set proxy info. </para>
764 public virtual IWebProxy Proxy {
766 throw ExceptionHelper.PropertyNotImplementedException;
769 throw ExceptionHelper.PropertyNotImplementedException;
774 /// <para>When overridden in a derived class,
775 /// enables or disables pre-authentication.</para>
777 public virtual bool PreAuthenticate {
779 throw ExceptionHelper.PropertyNotImplementedException;
782 throw ExceptionHelper.PropertyNotImplementedException;
787 // Timeout in milliseconds, if request takes longer
788 // than timeout, a WebException is thrown
792 /// <para>[To be supplied.]</para>
794 public virtual int Timeout {
796 throw ExceptionHelper.PropertyNotImplementedException;
799 throw ExceptionHelper.PropertyNotImplementedException;
805 /// <para>When overridden in a derived class,
806 /// returns a <see cref='System.IO.Stream'/> object that is used for writing data
807 /// to the resource identified by <see cref='WebRequest.RequestUri'/>
810 public virtual Stream GetRequestStream() {
811 throw ExceptionHelper.MethodNotImplementedException;
815 /// <para>When overridden in a derived class,
816 /// returns the response
817 /// to an Internet request.</para>
819 public virtual WebResponse GetResponse() {
820 Contract.Ensures(Contract.Result<WebResponse>() != null);
822 throw ExceptionHelper.MethodNotImplementedException;
826 /// <para>Asynchronous version of GetResponse.</para>
828 [HostProtection(ExternalThreading=true)]
829 public virtual IAsyncResult BeginGetResponse(AsyncCallback callback, object state) {
830 throw ExceptionHelper.MethodNotImplementedException;
835 /// <para>Returns a WebResponse object.</para>
837 public virtual WebResponse EndGetResponse(IAsyncResult asyncResult) {
838 throw ExceptionHelper.MethodNotImplementedException;
842 /// <para>Asynchronous version of GetRequestStream
845 [HostProtection(ExternalThreading=true)]
846 public virtual IAsyncResult BeginGetRequestStream(AsyncCallback callback, Object state) {
847 throw ExceptionHelper.MethodNotImplementedException;
851 /// <para>Returns a <see cref='System.IO.Stream'/> object that is used for writing data to the resource
852 /// identified by <see cref='System.Net.WebRequest.RequestUri'/>
855 public virtual Stream EndGetRequestStream(IAsyncResult asyncResult) {
856 throw ExceptionHelper.MethodNotImplementedException;
859 // Offload to a different thread to avoid blocking the caller durring request submission.
860 [HostProtection(ExternalThreading = true)]
861 public virtual Task<Stream> GetRequestStreamAsync()
863 IWebProxy proxy = null;
864 try { proxy = Proxy; }
865 catch (NotImplementedException) { }
867 // Preserve context for authentication
868 if (ExecutionContext.IsFlowSuppressed()
869 && (UseDefaultCredentials || Credentials != null
870 || (proxy != null && proxy.Credentials != null)))
872 WindowsIdentity currentUser = SafeCaptureIdenity();
874 // When flow is suppressed we would lose track of the current user across this thread switch.
875 // Flow manually so that UseDefaultCredentials will work. BeginGetRequestStream will
876 // take over from there.
877 return Task.Run(() =>
881 using (currentUser.Impersonate())
883 return Task<Stream>.Factory.FromAsync(this.BeginGetRequestStream,
884 this.EndGetRequestStream, null);
891 return Task.Run(() => Task<Stream>.Factory.FromAsync(this.BeginGetRequestStream,
892 this.EndGetRequestStream, null));
896 // Offload to a different thread to avoid blocking the caller durring request submission.
897 [HostProtection(ExternalThreading = true)]
898 public virtual Task<WebResponse> GetResponseAsync()
900 IWebProxy proxy = null;
901 try { proxy = Proxy; }
902 catch (NotImplementedException) { }
904 // Preserve context for authentication
905 if (ExecutionContext.IsFlowSuppressed()
906 && (UseDefaultCredentials || Credentials != null
907 || (proxy != null && proxy.Credentials != null)))
909 WindowsIdentity currentUser = SafeCaptureIdenity();
911 // When flow is suppressed we would lose track of the current user across this thread switch.
912 // Flow manually so that UseDefaultCredentials will work. BeginGetResponse will
913 // take over from there.
914 return Task.Run(() =>
918 using (currentUser.Impersonate())
920 return Task<WebResponse>.Factory.FromAsync(this.BeginGetResponse,
921 this.EndGetResponse, null);
928 return Task.Run(() => Task<WebResponse>.Factory.FromAsync(this.BeginGetResponse,
929 this.EndGetResponse, null));
933 // Security: We need an assert for a call into WindowsIdentity.GetCurrent
934 [SecuritySafeCritical]
935 [SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.ControlPrincipal)]
936 [SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Justification = "Needed for identity flow.")]
937 private WindowsIdentity SafeCaptureIdenity()
939 return WindowsIdentity.GetCurrent();
944 /// <para>Aborts the Request</para>
946 public virtual void Abort() {
947 throw ExceptionHelper.MethodNotImplementedException;
953 internal RequestCacheProtocol CacheProtocol
957 return m_CacheProtocol;
961 m_CacheProtocol = value;
969 public AuthenticationLevel AuthenticationLevel {
971 return m_AuthenticationLevel;
974 m_AuthenticationLevel = value;
979 // Methods to retrieve the context of the "reading phase" and of the "writing phase" of the request.
980 // Each request type can define what goes into what phase. Typically, the writing phase corresponds to
981 // GetRequestStream() and the reading phase to GetResponse(), but if there's no request body, both phases
982 // may happen inside GetResponse().
984 // Return null only on [....] (if we're on the [....] thread). Otherwise throw if no context is available.
985 internal virtual ContextAwareResult GetConnectingContext()
987 throw ExceptionHelper.MethodNotImplementedException;
990 internal virtual ContextAwareResult GetWritingContext()
992 throw ExceptionHelper.MethodNotImplementedException;
995 internal virtual ContextAwareResult GetReadingContext()
997 throw ExceptionHelper.MethodNotImplementedException;
1004 public TokenImpersonationLevel ImpersonationLevel {
1006 return m_ImpersonationLevel;
1009 m_ImpersonationLevel = value;
1012 #endif // !FEATURE_PAL
1015 /// <para>Provides an abstract way of having Async code callback into the request (saves a delegate)</para>
1017 internal virtual void RequestCallback(object obj) {
1018 throw ExceptionHelper.MethodNotImplementedException;
1022 // Default Web Proxy implementation.
1024 private static volatile IWebProxy s_DefaultWebProxy;
1025 private static volatile bool s_DefaultWebProxyInitialized;
1027 internal static IWebProxy InternalDefaultWebProxy
1031 if (!s_DefaultWebProxyInitialized)
1033 lock (InternalSyncObject)
1035 if (!s_DefaultWebProxyInitialized)
1037 GlobalLog.Print("WebRequest::get_InternalDefaultWebProxy(): Getting config.");
1038 DefaultProxySectionInternal section = DefaultProxySectionInternal.GetSection();
1039 if (section != null)
1041 s_DefaultWebProxy = section.WebProxy;
1043 s_DefaultWebProxyInitialized = true;
1047 return s_DefaultWebProxy;
1052 // Same lock as above. Avoid hitting config if the proxy is set first.
1053 if (!s_DefaultWebProxyInitialized)
1055 lock (InternalSyncObject)
1057 s_DefaultWebProxy = value;
1058 s_DefaultWebProxyInitialized = true;
1063 s_DefaultWebProxy = value;
1069 // Get and set the global default proxy. Use this instead of the old GlobalProxySelection.
1071 public static IWebProxy DefaultWebProxy
1075 ExceptionHelper.WebPermissionUnrestricted.Demand();
1076 return InternalDefaultWebProxy;
1081 ExceptionHelper.WebPermissionUnrestricted.Demand();
1082 InternalDefaultWebProxy = value;
1087 // This returns an "IE Proxy" based on the currently impersonated user's proxy settings.
1089 public static IWebProxy GetSystemWebProxy()
1091 ExceptionHelper.WebPermissionUnrestricted.Demand();
1092 return InternalGetSystemWebProxy();
1095 internal static IWebProxy InternalGetSystemWebProxy()
1097 return new WebProxyWrapperOpaque(new WebProxy(true));
1101 // To maintain backwards-compatibility, GlobalProxySelection.Select must return a proxy castable to WebProxy.
1102 // To get away from that restriction in the future, new APIs wrap the WebProxy in an internal wrapper.
1103 // Once Select is removed, the system-proxy functionality can be factored out of the WebProxy class.
1107 // This doesn't expose the WebProxy. It's used by GetSystemWebProxy(), which should never be castable to WebProxy.
1109 internal class WebProxyWrapperOpaque : IAutoWebProxy
1111 protected readonly WebProxy webProxy;
1113 internal WebProxyWrapperOpaque(WebProxy webProxy)
1115 this.webProxy = webProxy;
1118 public Uri GetProxy(Uri destination)
1120 return webProxy.GetProxy(destination);
1123 public bool IsBypassed(Uri host)
1125 return webProxy.IsBypassed(host);
1128 public ICredentials Credentials
1132 return webProxy.Credentials;
1137 webProxy.Credentials = value;
1141 public ProxyChain GetProxies(Uri destination)
1143 return ((IAutoWebProxy) webProxy).GetProxies(destination);
1148 // Select returns the WebProxy out of this one.
1150 internal class WebProxyWrapper : WebProxyWrapperOpaque
1152 internal WebProxyWrapper(WebProxy webProxy) :
1156 internal WebProxy WebProxy
1167 internal void SetupCacheProtocol(Uri uri)
1169 m_CacheBinding = RequestCacheManager.GetBinding(uri.Scheme);
1171 // Note if the cache is disabled it will give back a bypass policy.
1172 InternalSetCachePolicy( m_CacheBinding.Policy);
1173 if (m_CachePolicy == null)
1175 // If the protocol cache policy is not specifically configured, grab from the base class.
1176 InternalSetCachePolicy(WebRequest.DefaultCachePolicy);
1180 delegate void DelEtwFireBeginWRGet(object id, string uri, bool success, bool synchronous);
1181 delegate void DelEtwFireEndWRGet(object id, bool success, bool synchronous);
1182 delegate void DelEtwFireEndWRespGet(object id, bool success, bool synchronous, int statusCode);
1183 static DelEtwFireBeginWRGet s_EtwFireBeginGetResponse;
1184 static DelEtwFireEndWRespGet s_EtwFireEndGetResponse;
1185 static DelEtwFireBeginWRGet s_EtwFireBeginGetRequestStream;
1186 static DelEtwFireEndWRGet s_EtwFireEndGetRequestStream;
1187 static volatile bool s_TriedGetEtwDelegates;
1189 private static void InitEtwMethods()
1191 Type fest = typeof(FrameworkEventSource);
1192 var beginParamTypes = new Type[] { typeof(object), typeof(string), typeof(bool), typeof(bool) };
1193 var bindingFlags = BindingFlags.Instance|BindingFlags.NonPublic|BindingFlags.Public;
1194 var mi1 = fest.GetMethod("BeginGetResponse", bindingFlags, null, beginParamTypes, null);
1195 var mi2 = fest.GetMethod("EndGetResponse", bindingFlags, null, new Type[] { typeof(object), typeof(bool), typeof(bool), typeof(int) }, null);
1196 var mi3 = fest.GetMethod("BeginGetRequestStream", bindingFlags, null, beginParamTypes, null);
1197 var mi4 = fest.GetMethod("EndGetRequestStream", bindingFlags, null, new Type[] { typeof(object), typeof(bool), typeof(bool) }, null);
1198 if (mi1 != null && mi2 != null && mi3 != null && mi4 != null)
1200 s_EtwFireBeginGetResponse = (DelEtwFireBeginWRGet) mi1.CreateDelegate(typeof(DelEtwFireBeginWRGet), FrameworkEventSource.Log);
1201 s_EtwFireEndGetResponse = (DelEtwFireEndWRespGet)mi2.CreateDelegate(typeof(DelEtwFireEndWRespGet), FrameworkEventSource.Log);
1202 s_EtwFireBeginGetRequestStream = (DelEtwFireBeginWRGet) mi3.CreateDelegate(typeof(DelEtwFireBeginWRGet), FrameworkEventSource.Log);
1203 s_EtwFireEndGetRequestStream = (DelEtwFireEndWRGet) mi4.CreateDelegate(typeof(DelEtwFireEndWRGet), FrameworkEventSource.Log);
1205 s_TriedGetEtwDelegates = true;
1208 internal void LogBeginGetResponse(bool success, bool synchronous)
1210 string uri = this.RequestUri.OriginalString;
1211 if (!s_TriedGetEtwDelegates)
1213 if (s_EtwFireBeginGetResponse != null)
1215 s_EtwFireBeginGetResponse(this, uri, success, synchronous);
1218 internal void LogEndGetResponse(bool success, bool synchronous, int statusCode)
1220 if (!s_TriedGetEtwDelegates)
1222 if (s_EtwFireEndGetResponse != null) {
1223 s_EtwFireEndGetResponse(this, success, synchronous, statusCode);
1226 internal void LogBeginGetRequestStream(bool success, bool synchronous)
1228 string uri = this.RequestUri.OriginalString;
1229 if (!s_TriedGetEtwDelegates)
1231 if (s_EtwFireBeginGetRequestStream != null)
1233 s_EtwFireBeginGetRequestStream(this, uri, success, synchronous);
1236 internal void LogEndGetRequestStream(bool success, bool synchronous)
1238 if (!s_TriedGetEtwDelegates)
1240 if (s_EtwFireEndGetRequestStream != null) {
1242 s_EtwFireEndGetRequestStream(this, success, synchronous);
1245 } // class WebRequest
1246 } // namespace System.Net