/// <summary> /// Reads name=value pairs into a message. /// </summary> /// <param name="fields">The name=value pairs that were read in from the transport.</param> /// <param name="messageDictionary">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, MessageDictionary messageDictionary) { Contract.Requires <ArgumentNullException>(fields != null); Contract.Requires <ArgumentNullException>(messageDictionary != null); var messageDescription = messageDictionary.Description; // Before we deserialize the message, make sure all the required parts are present. messageDescription.EnsureMessagePartsPassBasicValidation(fields); try { foreach (var pair in fields) { messageDictionary[pair.Key] = pair.Value; } } catch (ArgumentException ex) { throw ErrorUtilities.Wrap(ex, MessagingStrings.ErrorDeserializingMessage, this.messageType.Name); } messageDictionary.Message.EnsureValidMessage(); }
/// <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) { // This request MAY have already been prepared by GetRequestStream, but // we have no guarantee, so do it just to be safe. PrepareRequest(request, false); try { Logger.Http.DebugFormat("HTTP {0} {1}", request.Method, request.RequestUri); HttpWebResponse response = (HttpWebResponse)request.GetResponse(); return(new NetworkDirectWebResponse(request.RequestUri, response)); } catch (WebException ex) { HttpWebResponse response = (HttpWebResponse)ex.Response; if (response != null && response.StatusCode == HttpStatusCode.ExpectationFailed && request.ServicePoint.Expect100Continue) { // Some OpenID servers doesn't understand the Expect header and send 417 error back. // If this server just failed from that, alter the ServicePoint for this server // so that we don't send that header again next time (whenever that is). // "Expect: 100-Continue" HTTP header. (see Google Code Issue 72) // We don't want to blindly set all ServicePoints to not use the Expect header // as that would be a security hole allowing any visitor to a web site change // the web site's global behavior when calling that host. Logger.Http.InfoFormat("HTTP POST to {0} resulted in 417 Expectation Failed. Changing ServicePoint to not use Expect: Continue next time.", request.RequestUri); request.ServicePoint.Expect100Continue = false; // TODO: investigate that CAS may throw here // An alternative to ServicePoint if we don't have permission to set that, // but we'd have to set it BEFORE each request. ////request.Expect = ""; } if ((options & DirectWebRequestOptions.AcceptAllHttpResponses) != 0 && response != null && response.StatusCode != HttpStatusCode.ExpectationFailed) { Logger.Http.InfoFormat("The HTTP error code {0} {1} is being accepted because the {2} flag is set.", (int)response.StatusCode, response.StatusCode, DirectWebRequestOptions.AcceptAllHttpResponses); return(new NetworkDirectWebResponse(request.RequestUri, response)); } if (Logger.Http.IsErrorEnabled) { if (response != null) { using (var reader = new StreamReader(ex.Response.GetResponseStream())) { Logger.Http.ErrorFormat("WebException from {0}: {1}{2}", ex.Response.ResponseUri, Environment.NewLine, reader.ReadToEnd()); } } else { Logger.Http.ErrorFormat("WebException {1} from {0}, no response available.", request.RequestUri, ex.Status); } } // Be sure to close the response stream to conserve resources and avoid // filling up all our incoming pipes and denying future requests. // If in the future, some callers actually want to read this response // we'll need to figure out how to reliably call Close on exception // responses at all callers. if (response != null) { response.Close(); } throw ErrorUtilities.Wrap(ex, MessagingStrings.ErrorInRequestReplyMessage); } }