/// <summary> /// Encodes an HTTP response that will instruct the user agent to forward a message to /// some remote third party using a form POST method. /// </summary> /// <param name="message">The message to forward.</param> /// <param name="fields">The pre-serialized fields from the message.</param> /// <returns>The encoded HTTP response.</returns> protected virtual UserAgentResponse CreateFormPostResponse(IDirectedProtocolMessage message, IDictionary <string, string> fields) { ErrorUtilities.VerifyArgumentNotNull(message, "message"); ErrorUtilities.VerifyArgumentNamed(message.Recipient != null, "message", MessagingStrings.DirectedMessageMissingRecipient); ErrorUtilities.VerifyArgumentNotNull(fields, "fields"); WebHeaderCollection headers = new WebHeaderCollection(); StringWriter bodyWriter = new StringWriter(CultureInfo.InvariantCulture); StringBuilder hiddenFields = new StringBuilder(); foreach (var field in fields) { hiddenFields.AppendFormat( "\t<input type=\"hidden\" name=\"{0}\" value=\"{1}\" />\r\n", HttpUtility.HtmlEncode(field.Key), HttpUtility.HtmlEncode(field.Value)); } bodyWriter.WriteLine( indirectMessageFormPostFormat, HttpUtility.HtmlEncode(message.Recipient.AbsoluteUri), hiddenFields); bodyWriter.Flush(); UserAgentResponse response = new UserAgentResponse { Status = HttpStatusCode.OK, Headers = headers, Body = bodyWriter.ToString(), OriginalMessage = message }; return(response); }
/// <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 writer 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.</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) { ErrorUtilities.VerifyArgumentNotNull(request, "request"); ErrorUtilities.VerifySupported(this.CanSupport(options), MessagingStrings.DirectWebRequestOptionsNotSupported, options, this.GetType().Name); return(GetRequestStreamCore(request, options)); }
/// <summary> /// Prepares to send a request to the Service Provider as the payload of a POST request. /// </summary> /// <param name="requestMessage">The message to be transmitted to the ServiceProvider.</param> /// <returns>The web request ready to send.</returns> /// <remarks> /// This method is simply a standard HTTP POST request with the message parts serialized to the POST entity /// with the application/x-www-form-urlencoded content type /// This method satisfies OAuth 1.0 section 5.2, item #2 and OpenID 2.0 section 4.1.2. /// </remarks> protected virtual HttpWebRequest InitializeRequestAsPost(IDirectedProtocolMessage requestMessage) { ErrorUtilities.VerifyArgumentNotNull(requestMessage, "requestMessage"); var serializer = MessageSerializer.Get(requestMessage.GetType()); var fields = serializer.Serialize(requestMessage); HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(requestMessage.Recipient); httpRequest.CachePolicy = this.CachePolicy; httpRequest.Method = "POST"; httpRequest.ContentType = "application/x-www-form-urlencoded"; httpRequest.Headers[HttpRequestHeader.ContentEncoding] = PostEntityEncoding.WebName; string requestBody = MessagingUtilities.CreateQueryString(fields); byte[] requestBytes = PostEntityEncoding.GetBytes(requestBody); httpRequest.ContentLength = requestBytes.Length; Stream requestStream = this.WebRequestHandler.GetRequestStream(httpRequest); try { requestStream.Write(requestBytes, 0, requestBytes.Length); } finally { // We need to be sure to close the request stream... // unless it is a MemoryStream, which is a clue that we're in // a mock stream situation and closing it would preclude reading it later. if (!(requestStream is MemoryStream)) { requestStream.Dispose(); } } return(httpRequest); }
/// <summary> /// Initializes a new instance of the <see cref="CachedDirectWebResponse"/> class. /// </summary> /// <param name="requestUri">The request URI.</param> /// <param name="responseUri">The final URI to respond to the request.</param> /// <param name="headers">The headers.</param> /// <param name="statusCode">The status code.</param> /// <param name="contentType">Type of the content.</param> /// <param name="contentEncoding">The content encoding.</param> /// <param name="responseStream">The response stream.</param> internal CachedDirectWebResponse(Uri requestUri, Uri responseUri, WebHeaderCollection headers, HttpStatusCode statusCode, string contentType, string contentEncoding, MemoryStream responseStream) : base(requestUri, responseUri, headers, statusCode, contentType, contentEncoding) { ErrorUtilities.VerifyArgumentNotNull(responseStream, "responseStream"); this.responseStream = responseStream; }
internal IDictionary <string, string> Serialize(IMessage message) { ErrorUtilities.VerifyArgumentNotNull(message, "message"); var messageDescription = MessageDescription.Get(this.messageType, message.Version); var messageDictionary = new MessageDictionary(message); // Rather than hand back the whole message dictionary (which // includes keys with blank values), create a new dictionary // that only has required keys, and optional keys whose // values are not empty. var result = new Dictionary <string, string>(); foreach (var pair in messageDictionary) { MessagePart partDescription; if (messageDescription.Mapping.TryGetValue(pair.Key, out partDescription)) { if (partDescription.IsRequired || partDescription.IsNondefaultValueSet(message)) { result.Add(pair.Key, pair.Value); } } else { // This is extra data. We always write it out. result.Add(pair.Key, pair.Value); } } return(result); }
/// <summary> /// Initializes a new instance of the <see cref="MessageReceivingEndpoint"/> class. /// </summary> /// <param name="location">The URL of this endpoint.</param> /// <param name="method">The HTTP method(s) allowed.</param> public MessageReceivingEndpoint(Uri location, HttpDeliveryMethods method) { ErrorUtilities.VerifyArgumentNotNull(location, "location"); ErrorUtilities.VerifyArgumentInRange(method != HttpDeliveryMethods.None, "method"); ErrorUtilities.VerifyArgumentInRange((method & (HttpDeliveryMethods.PostRequest | HttpDeliveryMethods.GetRequest)) != 0, "method", MessagingStrings.GetOrPostFlagsRequired); this.Location = location; this.AllowedMethods = method; }
/// <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 writer 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.</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) { ErrorUtilities.VerifyArgumentNotNull(request, "request"); this.EnsureAllowableRequestUri(request.RequestUri, (options & DirectWebRequestOptions.RequireSsl) != 0); this.PrepareRequest(request, true); // Submit the request and get the request stream back. return(this.chainedWebRequestHandler.GetRequestStream(request, options & ~DirectWebRequestOptions.RequireSsl)); }
/// <summary> /// Creates a snapshot of some stream so it is seekable, and the original can be closed. /// </summary> /// <param name="copyFrom">The stream to copy bytes from.</param> /// <returns>A seekable stream with the same contents as the original.</returns> internal static Stream CreateSnapshot(this Stream copyFrom) { ErrorUtilities.VerifyArgumentNotNull(copyFrom, "copyFrom"); MemoryStream copyTo = new MemoryStream(copyFrom.CanSeek ? (int)copyFrom.Length : 4 * 1024); copyFrom.CopyTo(copyTo); copyTo.Position = 0; return(copyTo); }
/// <summary> /// Fires the <see cref="Sending"/> event. /// </summary> /// <param name="message">The message about to be encoded and sent.</param> protected virtual void OnSending(IProtocolMessage message) { ErrorUtilities.VerifyArgumentNotNull(message, "message"); var sending = this.Sending; if (sending != null) { sending(this, new ChannelEventArgs(message)); } }
/// <summary> /// Prepares a message for transmit by applying signatures, nonces, etc. /// </summary> /// <param name="message">The message to prepare for sending.</param> /// <remarks> /// This method should NOT be called by derived types /// except when sending ONE WAY request messages. /// </remarks> protected void PrepareMessageForSending(IProtocolMessage message) { ErrorUtilities.VerifyArgumentNotNull(message, "message"); Logger.DebugFormat("Preparing to send {0} ({1}) message.", message.GetType().Name, message.Version); this.OnSending(message); // Give the message a chance to do custom serialization. IMessageWithEvents eventedMessage = message as IMessageWithEvents; if (eventedMessage != null) { eventedMessage.OnSending(); } MessageProtections appliedProtection = MessageProtections.None; foreach (IChannelBindingElement bindingElement in this.outgoingBindingElements) { if (bindingElement.PrepareMessageForSending(message)) { Logger.DebugFormat("Binding element {0} applied to message.", bindingElement.GetType().FullName); // Ensure that only one protection binding element applies to this message // for each protection type. ErrorUtilities.VerifyProtocol((appliedProtection & bindingElement.Protection) == 0, MessagingStrings.TooManyBindingsOfferingSameProtection, bindingElement.Protection); appliedProtection |= bindingElement.Protection; } else { Logger.DebugFormat("Binding element {0} did not apply to message.", bindingElement.GetType().FullName); } } // Ensure that the message's protection requirements have been satisfied. if ((message.RequiredProtection & appliedProtection) != message.RequiredProtection) { throw new UnprotectedMessageException(message, appliedProtection); } EnsureValidMessageParts(message); message.EnsureValidMessage(); if (Logger.IsDebugEnabled) { Logger.DebugFormat( "Sending {0} ({1}) message: {2}{3}", message.GetType().Name, message.Version, Environment.NewLine, new MessageDictionary(message).ToStringDeferred()); } }
/// <summary> /// Copies some extra parameters into a message. /// </summary> /// <param name="message">The message to copy the extra data into.</param> /// <param name="extraParameters">The extra data to copy into the message. May be null to do nothing.</param> internal static void AddExtraParameters(this IMessage message, IDictionary <string, string> extraParameters) { ErrorUtilities.VerifyArgumentNotNull(message, "message"); if (extraParameters != null) { MessageDictionary messageDictionary = new MessageDictionary(message); foreach (var pair in extraParameters) { messageDictionary.Add(pair); } } }
/// <summary> /// Initializes a new instance of the <see cref="UserAgentResponse"/> class /// based on the contents of an <see cref="HttpWebResponse"/>. /// </summary> /// <param name="response">The <see cref="HttpWebResponse"/> to clone.</param> /// <param name="maximumBytesToRead">The maximum bytes to read from the response stream.</param> protected internal UserAgentResponse(HttpWebResponse response, int maximumBytesToRead) { ErrorUtilities.VerifyArgumentNotNull(response, "response"); this.Status = response.StatusCode; this.Headers = response.Headers; this.ResponseStream = new MemoryStream(response.ContentLength < 0 ? 4 * 1024 : (int)response.ContentLength); using (Stream responseStream = response.GetResponseStream()) { // BUGBUG: strictly speaking, is the response were exactly the limit, we'd report it as truncated here. this.IsResponseTruncated = responseStream.CopyTo(this.ResponseStream, maximumBytesToRead) == maximumBytesToRead; this.ResponseStream.Seek(0, SeekOrigin.Begin); } }
/// <summary> /// Customizes the binding element order for outgoing and incoming messages. /// </summary> /// <param name="outgoingOrder">The outgoing order.</param> /// <param name="incomingOrder">The incoming order.</param> /// <remarks> /// No binding elements can be added or removed from the channel using this method. /// Only a customized order is allowed. /// </remarks> /// <exception cref="ArgumentException">Thrown if a binding element is new or missing in one of the ordered lists.</exception> protected void CustomizeBindingElementOrder(IEnumerable <IChannelBindingElement> outgoingOrder, IEnumerable <IChannelBindingElement> incomingOrder) { ErrorUtilities.VerifyArgumentNotNull(outgoingOrder, "outgoingOrder"); ErrorUtilities.VerifyArgumentNotNull(incomingOrder, "incomingOrder"); ErrorUtilities.VerifyArgument(this.IsBindingElementOrderValid(outgoingOrder), MessagingStrings.InvalidCustomBindingElementOrder); ErrorUtilities.VerifyArgument(this.IsBindingElementOrderValid(incomingOrder), MessagingStrings.InvalidCustomBindingElementOrder); this.outgoingBindingElements.Clear(); this.outgoingBindingElements.AddRange(outgoingOrder); this.incomingBindingElements.Clear(); this.incomingBindingElements.AddRange(incomingOrder); }
/// <summary> /// Initializes a new instance of the <see cref="DirectWebResponse"/> class. /// </summary> /// <param name="requestUri">The request URI.</param> /// <param name="responseUri">The final URI to respond to the request.</param> /// <param name="headers">The headers.</param> /// <param name="statusCode">The status code.</param> /// <param name="contentType">Type of the content.</param> /// <param name="contentEncoding">The content encoding.</param> protected DirectWebResponse(Uri requestUri, Uri responseUri, WebHeaderCollection headers, HttpStatusCode statusCode, string contentType, string contentEncoding) { ErrorUtilities.VerifyArgumentNotNull(requestUri, "requestUri"); this.RequestUri = requestUri; this.Status = statusCode; if (!string.IsNullOrEmpty(contentType)) { this.ContentType = new ContentType(contentType); } this.ContentEncoding = string.IsNullOrEmpty(contentEncoding) ? DefaultContentEncoding : contentEncoding; this.Headers = headers; this.FinalUri = responseUri; }
/// <summary> /// Prepares to send a request to the Service Provider as the query string in a GET request. /// </summary> /// <param name="requestMessage">The message to be transmitted to the ServiceProvider.</param> /// <returns>The web request ready to send.</returns> /// <remarks> /// This method is simply a standard HTTP Get request with the message parts serialized to the query string. /// This method satisfies OAuth 1.0 section 5.2, item #3. /// </remarks> protected virtual HttpWebRequest InitializeRequestAsGet(IDirectedProtocolMessage requestMessage) { ErrorUtilities.VerifyArgumentNotNull(requestMessage, "requestMessage"); var serializer = MessageSerializer.Get(requestMessage.GetType()); var fields = serializer.Serialize(requestMessage); UriBuilder builder = new UriBuilder(requestMessage.Recipient); MessagingUtilities.AppendQueryArgs(builder, fields); HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(builder.Uri); return(httpRequest); }
/// <summary> /// Prepares an HTTP request. /// </summary> /// <param name="request">The request.</param> /// <param name="preparingPost"><c>true</c> if this is a POST request whose headers have not yet been sent out; <c>false</c> otherwise.</param> private static void PrepareRequest(HttpWebRequest request, bool preparingPost) { ErrorUtilities.VerifyArgumentNotNull(request, "request"); // Be careful to not try to change the HTTP headers that have already gone out. if (preparingPost || request.Method == "GET") { // Some sites, such as Technorati, return 403 Forbidden on identity // pages unless a User-Agent header is included. if (string.IsNullOrEmpty(request.UserAgent)) { request.UserAgent = userAgentValue; } } }
/// <summary> /// Initializes a new instance of the <see cref="Channel"/> class. /// </summary> /// <param name="messageTypeProvider"> /// A class prepared to analyze incoming messages and indicate what concrete /// message types can deserialize from it. /// </param> /// <param name="bindingElements">The binding elements to use in sending and receiving messages.</param> protected Channel(IMessageFactory messageTypeProvider, params IChannelBindingElement[] bindingElements) { ErrorUtilities.VerifyArgumentNotNull(messageTypeProvider, "messageTypeProvider"); this.messageTypeProvider = messageTypeProvider; this.WebRequestHandler = new StandardWebRequestHandler(); this.outgoingBindingElements = new List <IChannelBindingElement>(ValidateAndPrepareBindingElements(bindingElements)); this.incomingBindingElements = new List <IChannelBindingElement>(this.outgoingBindingElements); this.incomingBindingElements.Reverse(); foreach (var element in this.outgoingBindingElements) { element.Channel = this; } }
/// <summary> /// Adds parameters to a query string, replacing parameters that /// match ones that already exist in the query string. /// </summary> /// <param name="builder">The UriBuilder to add arguments to.</param> /// <param name="args"> /// The arguments to add to the query. /// If null, <paramref name="builder"/> is not changed. /// </param> internal static void AppendAndReplaceQueryArgs(this UriBuilder builder, IEnumerable <KeyValuePair <string, string> > args) { ErrorUtilities.VerifyArgumentNotNull(builder, "builder"); if (args != null && args.Count() > 0) { NameValueCollection aggregatedArgs = HttpUtility.ParseQueryString(builder.Query); foreach (var pair in args) { aggregatedArgs[pair.Key] = pair.Value; } builder.Query = CreateQueryString(aggregatedArgs.ToDictionary()); } }
/// <summary> /// Sends a direct message to a remote party and waits for the response. /// </summary> /// <param name="requestMessage">The message to send.</param> /// <returns>The remote party's response. Guaranteed to never be null.</returns> /// <exception cref="ProtocolException">Thrown if the response does not include a protocol message.</exception> public IProtocolMessage Request(IDirectedProtocolMessage requestMessage) { ErrorUtilities.VerifyArgumentNotNull(requestMessage, "requestMessage"); this.PrepareMessageForSending(requestMessage); Logger.DebugFormat("Sending request: {0}", requestMessage); var responseMessage = this.RequestInternal(requestMessage); ErrorUtilities.VerifyProtocol(responseMessage != null, MessagingStrings.ExpectedMessageNotReceived, typeof(IProtocolMessage).Name); Logger.DebugFormat("Received message response: {0}", responseMessage); this.VerifyMessageAfterReceiving(responseMessage); return(responseMessage); }
/// <summary> /// Initializes a new instance of the <see cref="DirectWebResponse"/> class. /// </summary> /// <param name="requestUri">The original request URI.</param> /// <param name="response">The response to initialize from. The network stream is used by this class directly.</param> protected DirectWebResponse(Uri requestUri, HttpWebResponse response) { ErrorUtilities.VerifyArgumentNotNull(requestUri, "requestUri"); ErrorUtilities.VerifyArgumentNotNull(response, "response"); this.RequestUri = requestUri; if (!string.IsNullOrEmpty(response.ContentType)) { this.ContentType = new ContentType(response.ContentType); } this.ContentEncoding = string.IsNullOrEmpty(response.ContentEncoding) ? DefaultContentEncoding : response.ContentEncoding; this.FinalUri = response.ResponseUri; this.Status = response.StatusCode; this.Headers = response.Headers; }
/// <summary> /// Gets the protocol message that may be embedded in the given HTTP request. /// </summary> /// <param name="request">The request to search for an embedded message.</param> /// <returns>The deserialized message, if one is found. Null otherwise.</returns> protected virtual IDirectedProtocolMessage ReadFromRequestInternal(HttpRequestInfo request) { ErrorUtilities.VerifyArgumentNotNull(request, "request"); Logger.DebugFormat("Incoming HTTP request: {0}", request.Url.AbsoluteUri); // Search Form data first, and if nothing is there search the QueryString var fields = request.Form.ToDictionary(); if (fields.Count == 0) { fields = request.QueryString.ToDictionary(); } return((IDirectedProtocolMessage)this.Receive(fields, request.GetRecipient())); }
/// <summary> /// Caches the network stream and closes it if it is open. /// </summary> /// <param name="response">The response whose stream is to be cloned.</param> /// <param name="maximumBytesToRead">The maximum bytes to cache.</param> /// <returns>The seekable Stream instance that contains a copy of what was returned in the HTTP response.</returns> private static MemoryStream CacheNetworkStreamAndClose(HttpWebResponse response, int maximumBytesToRead) { ErrorUtilities.VerifyArgumentNotNull(response, "response"); // Now read and cache the network stream Stream networkStream = response.GetResponseStream(); MemoryStream cachedStream = new MemoryStream(response.ContentLength < 0 ? 4 * 1024 : Math.Min((int)response.ContentLength, maximumBytesToRead)); networkStream.CopyTo(cachedStream); cachedStream.Seek(0, SeekOrigin.Begin); networkStream.Dispose(); response.Close(); return(cachedStream); }
/// <summary> /// Determines whether an IP address is the IPv6 equivalent of "localhost/127.0.0.1". /// </summary> /// <param name="ip">The ip address to check.</param> /// <returns> /// <c>true</c> if this is a loopback IP address; <c>false</c> otherwise. /// </returns> private static bool IsIPv6Loopback(IPAddress ip) { ErrorUtilities.VerifyArgumentNotNull(ip, "ip"); byte[] addressBytes = ip.GetAddressBytes(); for (int i = 0; i < addressBytes.Length - 1; i++) { if (addressBytes[i] != 0) { return(false); } } if (addressBytes[addressBytes.Length - 1] != 1) { return(false); } return(true); }
/// <summary> /// Adds a set of name-value pairs to the end of a given URL /// as part of the querystring piece. Prefixes a ? or & before /// first element as necessary. /// </summary> /// <param name="builder">The UriBuilder to add arguments to.</param> /// <param name="args"> /// The arguments to add to the query. /// If null, <paramref name="builder"/> is not changed. /// </param> /// <remarks> /// If the parameters to add match names of parameters that already are defined /// in the query string, the existing ones are <i>not</i> replaced. /// </remarks> internal static void AppendQueryArgs(this UriBuilder builder, IEnumerable <KeyValuePair <string, string> > args) { ErrorUtilities.VerifyArgumentNotNull(builder, "builder"); if (args != null && args.Count() > 0) { StringBuilder sb = new StringBuilder(50 + (args.Count() * 10)); if (!string.IsNullOrEmpty(builder.Query)) { sb.Append(builder.Query.Substring(1)); sb.Append('&'); } sb.Append(CreateQueryString(args)); builder.Query = sb.ToString(); } }
/// <summary> /// Tests whether two arrays are equal in contents and ordering. /// </summary> /// <typeparam name="T">The type of elements in the arrays.</typeparam> /// <param name="first">The first array in the comparison. May not be null.</param> /// <param name="second">The second array in the comparison. May not be null.</param> /// <returns>True if the arrays equal; false otherwise.</returns> internal static bool AreEquivalent <T>(T[] first, T[] second) { ErrorUtilities.VerifyArgumentNotNull(first, "first"); ErrorUtilities.VerifyArgumentNotNull(second, "second"); if (first.Length != second.Length) { return(false); } for (int i = 0; i < first.Length; i++) { if (!first[i].Equals(second[i])) { return(false); } } return(true); }
/// <summary> /// Determines whether a given ordered list of binding elements includes every /// binding element in this channel exactly once. /// </summary> /// <param name="order">The list of binding elements to test.</param> /// <returns> /// <c>true</c> if the given list is a valid description of a binding element ordering; otherwise, <c>false</c>. /// </returns> private bool IsBindingElementOrderValid(IEnumerable <IChannelBindingElement> order) { ErrorUtilities.VerifyArgumentNotNull(order, "order"); // Check that the same number of binding elements are defined. if (order.Count() != this.OutgoingBindingElements.Count) { return(false); } // Check that every binding element appears exactly once. if (order.Any(el => !this.OutgoingBindingElements.Contains(el))) { return(false); } return(true); }
/// <summary> /// Prepares the request by setting timeout and redirect policies. /// </summary> /// <param name="request">The request to prepare.</param> /// <param name="preparingPost"><c>true</c> if this is a POST request whose headers have not yet been sent out; <c>false</c> otherwise.</param> private void PrepareRequest(HttpWebRequest request, bool preparingPost) { ErrorUtilities.VerifyArgumentNotNull(request, "request"); // Be careful to not try to change the HTTP headers that have already gone out. if (preparingPost || request.Method == "GET") { // Set/override a few properties of the request to apply our policies for untrusted requests. request.ReadWriteTimeout = (int)this.ReadWriteTimeout.TotalMilliseconds; request.Timeout = (int)this.Timeout.TotalMilliseconds; request.KeepAlive = false; // If SSL is required throughout, we cannot allow auto redirects because // it may include a pass through an unprotected HTTP request. // We have to follow redirects manually. request.AllowAutoRedirect = false; } }
/// <summary> /// Queues an indirect message for transmittal via the user agent. /// </summary> /// <param name="message">The message to send.</param> /// <returns>The pending user agent redirect based message to be sent as an HttpResponse.</returns> protected virtual UserAgentResponse SendIndirectMessage(IDirectedProtocolMessage message) { ErrorUtilities.VerifyArgumentNotNull(message, "message"); var serializer = MessageSerializer.Get(message.GetType()); var fields = serializer.Serialize(message); // First try creating a 301 redirect, and fallback to a form POST // if the message is too big. UserAgentResponse response = this.Create301RedirectResponse(message, fields); if (response.Headers[HttpResponseHeader.Location].Length > indirectMessageGetToPostThreshold) { response = this.CreateFormPostResponse(message, fields); } return(response); }
/// <summary> /// Initializes a new instance of the <see cref="UntrustedWebRequestHandler"/> class. /// </summary> /// <param name="chainedWebRequestHandler">The chained web request handler.</param> public UntrustedWebRequestHandler(IDirectWebRequestHandler chainedWebRequestHandler) { ErrorUtilities.VerifyArgumentNotNull(chainedWebRequestHandler, "chainedWebRequestHandler"); this.chainedWebRequestHandler = chainedWebRequestHandler; if (Debugger.IsAttached) { // Since a debugger is attached, requests may be MUCH slower, // so give ourselves huge timeouts. this.ReadWriteTimeout = TimeSpan.FromHours(1); this.Timeout = TimeSpan.FromHours(1); } else { this.ReadWriteTimeout = Configuration.ReadWriteTimeout; this.Timeout = Configuration.Timeout; } }
/// <summary> /// Reads name=value pairs into an OAuth message. /// </summary> /// <param name="fields">The name=value pairs that were read in from the transport.</param> /// <param name="message">The message to deserialize into.</param> /// <exception cref="ProtocolException">Thrown when protocol rules are broken by the incoming message.</exception> internal void Deserialize(IDictionary <string, string> fields, IMessage message) { ErrorUtilities.VerifyArgumentNotNull(fields, "fields"); ErrorUtilities.VerifyArgumentNotNull(message, "message"); // Before we deserialize the message, make sure all the required parts are present. MessageDescription.Get(this.messageType, message.Version).EnsureMessagePartsPassBasicValidation(fields); try { foreach (var pair in fields) { IDictionary <string, string> dictionary = new MessageDictionary(message); dictionary[pair.Key] = pair.Value; } } catch (ArgumentException ex) { throw ErrorUtilities.Wrap(ex, MessagingStrings.ErrorDeserializingMessage, this.messageType.Name); } message.EnsureValidMessage(); }