diff options
author | Andrew Arnott <andrewarnott@gmail.com> | 2010-07-19 20:26:51 -0700 |
---|---|---|
committer | Andrew Arnott <andrewarnott@gmail.com> | 2010-07-19 20:26:51 -0700 |
commit | 0cfab05dbcb1449f692e227cb06a103a230c18a9 (patch) | |
tree | 90fd9911e7ac045d1b3784136e03e4b744d05fac /samples/DotNetOpenAuth.ApplicationBlock/Util.cs | |
parent | cc2073706f7d1d3d331883433c0b79028c4eb204 (diff) | |
parent | e615d3c78021d4326ec1442906576defed1d2aa7 (diff) | |
download | DotNetOpenAuth-0cfab05dbcb1449f692e227cb06a103a230c18a9.zip DotNetOpenAuth-0cfab05dbcb1449f692e227cb06a103a230c18a9.tar.gz DotNetOpenAuth-0cfab05dbcb1449f692e227cb06a103a230c18a9.tar.bz2 |
Merge branch 'v3.0' into v3.1
Conflicts:
samples/DotNetOpenAuth.ApplicationBlock/Util.cs
Diffstat (limited to 'samples/DotNetOpenAuth.ApplicationBlock/Util.cs')
-rw-r--r-- | samples/DotNetOpenAuth.ApplicationBlock/Util.cs | 183 |
1 files changed, 182 insertions, 1 deletions
diff --git a/samples/DotNetOpenAuth.ApplicationBlock/Util.cs b/samples/DotNetOpenAuth.ApplicationBlock/Util.cs index 8a188ac..64b35cb 100644 --- a/samples/DotNetOpenAuth.ApplicationBlock/Util.cs +++ b/samples/DotNetOpenAuth.ApplicationBlock/Util.cs @@ -1,13 +1,45 @@ namespace DotNetOpenAuth.ApplicationBlock { using System; using System.Collections.Generic; + using System.Diagnostics; using System.IO; + using System.Net; using DotNetOpenAuth.Messaging; - internal static class Util { + public static class Util { + /// <summary> + /// Pseudo-random data generator. + /// </summary> internal static readonly Random NonCryptoRandomDataGenerator = new Random(); /// <summary> + /// Sets the channel's outgoing HTTP requests to use default network credentials. + /// </summary> + /// <param name="channel">The channel to modify.</param> + public static void UseDefaultNetworkCredentialsOnOutgoingHttpRequests(this Channel channel) + { + Debug.Assert(!(channel.WebRequestHandler is WrappingWebRequestHandler), "Wrapping an already wrapped web request handler. This is legal, but highly suspect of a bug as you don't want to wrap the same channel repeatedly to apply the same effect."); + AddOutgoingHttpRequestTransform(channel, http => http.Credentials = CredentialCache.DefaultNetworkCredentials); + } + + /// <summary> + /// Adds some action to any outgoing HTTP request on this channel. + /// </summary> + /// <param name="channel">The channel's whose outgoing HTTP requests should be modified.</param> + /// <param name="action">The action to perform on outgoing HTTP requests.</param> + internal static void AddOutgoingHttpRequestTransform(this Channel channel, Action<HttpWebRequest> action) { + if (channel == null) { + throw new ArgumentNullException("channel"); + } + + if (action == null) { + throw new ArgumentNullException("action"); + } + + channel.WebRequestHandler = new WrappingWebRequestHandler(channel.WebRequestHandler, action); + } + + /// <summary> /// Enumerates through the individual set bits in a flag enum. /// </summary> /// <param name="flags">The flags enum value.</param> @@ -85,5 +117,154 @@ return totalCopiedBytes; } + + /// <summary> + /// Wraps some instance of a web request handler in order to perform some extra operation on all + /// outgoing HTTP requests. + /// </summary> + private class WrappingWebRequestHandler : IDirectWebRequestHandler + { + /// <summary> + /// The handler being wrapped. + /// </summary> + private readonly IDirectWebRequestHandler wrappedHandler; + + /// <summary> + /// The action to perform on outgoing HTTP requests. + /// </summary> + private readonly Action<HttpWebRequest> action; + + /// <summary> + /// Initializes a new instance of the <see cref="WrappingWebRequestHandler"/> class. + /// </summary> + /// <param name="wrappedHandler">The HTTP handler to wrap.</param> + /// <param name="action">The action to perform on outgoing HTTP requests.</param> + internal WrappingWebRequestHandler(IDirectWebRequestHandler wrappedHandler, Action<HttpWebRequest> action) + { + if (wrappedHandler == null) { + throw new ArgumentNullException("wrappedHandler"); + } + + if (action == null) { + throw new ArgumentNullException("action"); + } + + this.wrappedHandler = wrappedHandler; + this.action = action; + } + + #region Implementation of IDirectWebRequestHandler + + /// <summary> + /// Determines whether this instance can support the specified options. + /// </summary> + /// <param name="options">The set of options that might be given in a subsequent web request.</param> + /// <returns> + /// <c>true</c> if this instance can support the specified options; otherwise, <c>false</c>. + /// </returns> + public bool CanSupport(DirectWebRequestOptions options) + { + return this.wrappedHandler.CanSupport(options); + } + + /// <summary> + /// Prepares an <see cref="HttpWebRequest"/> that contains an POST entity for sending the entity. + /// </summary> + /// <param name="request">The <see cref="HttpWebRequest"/> that should contain the entity.</param> + /// <returns> + /// The stream the caller should write out the entity data to. + /// </returns> + /// <exception cref="ProtocolException">Thrown for any network error.</exception> + /// <remarks> + /// <para>The caller should have set the <see cref="HttpWebRequest.ContentLength"/> + /// and any other appropriate properties <i>before</i> calling this method. + /// Callers <i>must</i> close and dispose of the request stream when they are done + /// writing to it to avoid taking up the connection too long and causing long waits on + /// subsequent requests.</para> + /// <para>Implementations should catch <see cref="WebException"/> and wrap it in a + /// <see cref="ProtocolException"/> to abstract away the transport and provide + /// a single exception type for hosts to catch.</para> + /// </remarks> + public Stream GetRequestStream(HttpWebRequest request) + { + this.action(request); + return wrappedHandler.GetRequestStream(request); + } + + /// <summary> + /// Prepares an <see cref="HttpWebRequest"/> that contains an POST entity for sending the entity. + /// </summary> + /// <param name="request">The <see cref="HttpWebRequest"/> that should contain the entity.</param> + /// <param name="options">The options to apply to this web request.</param> + /// <returns> + /// The stream the caller should write out the entity data to. + /// </returns> + /// <exception cref="ProtocolException">Thrown for any network error.</exception> + /// <remarks> + /// <para>The caller should have set the <see cref="HttpWebRequest.ContentLength"/> + /// and any other appropriate properties <i>before</i> calling this method. + /// Callers <i>must</i> close and dispose of the request stream when they are done + /// writing to it to avoid taking up the connection too long and causing long waits on + /// subsequent requests.</para> + /// <para>Implementations should catch <see cref="WebException"/> and wrap it in a + /// <see cref="ProtocolException"/> to abstract away the transport and provide + /// a single exception type for hosts to catch.</para> + /// </remarks> + public Stream GetRequestStream(HttpWebRequest request, DirectWebRequestOptions options) + { + this.action(request); + return wrappedHandler.GetRequestStream(request, options); + } + + /// <summary> + /// Processes an <see cref="HttpWebRequest"/> and converts the + /// <see cref="HttpWebResponse"/> to a <see cref="IncomingWebResponse"/> instance. + /// </summary> + /// <param name="request">The <see cref="HttpWebRequest"/> to handle.</param> + /// <returns>An instance of <see cref="IncomingWebResponse"/> describing the response.</returns> + /// <exception cref="ProtocolException">Thrown for any network error.</exception> + /// <remarks> + /// <para>Implementations should catch <see cref="WebException"/> and wrap it in a + /// <see cref="ProtocolException"/> to abstract away the transport and provide + /// a single exception type for hosts to catch. The <see cref="WebException.Response"/> + /// value, if set, should be Closed before throwing.</para> + /// </remarks> + public IncomingWebResponse GetResponse(HttpWebRequest request) + { + // If the request has an entity, the action would have already been processed in GetRequestStream. + if (request.Method == "GET") + { + this.action(request); + } + + return wrappedHandler.GetResponse(request); + } + + /// <summary> + /// Processes an <see cref="HttpWebRequest"/> and converts the + /// <see cref="HttpWebResponse"/> to a <see cref="IncomingWebResponse"/> instance. + /// </summary> + /// <param name="request">The <see cref="HttpWebRequest"/> to handle.</param> + /// <param name="options">The options to apply to this web request.</param> + /// <returns>An instance of <see cref="IncomingWebResponse"/> describing the response.</returns> + /// <exception cref="ProtocolException">Thrown for any network error.</exception> + /// <remarks> + /// <para>Implementations should catch <see cref="WebException"/> and wrap it in a + /// <see cref="ProtocolException"/> to abstract away the transport and provide + /// a single exception type for hosts to catch. The <see cref="WebException.Response"/> + /// value, if set, should be Closed before throwing.</para> + /// </remarks> + public IncomingWebResponse GetResponse(HttpWebRequest request, DirectWebRequestOptions options) + { + // If the request has an entity, the action would have already been processed in GetRequestStream. + if (request.Method == "GET") { + this.action(request); + } + + return wrappedHandler.GetResponse(request, options); + } + + #endregion + } } } |