/// <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); }
public IProtocolMessage RequestAsync(IDirectedProtocolMessage requestMessage, CancellationToken cancellationToken) { this.ProcessOutgoingMessageAsync(requestMessage, cancellationToken); Logger.Channel.DebugFormat("Sending {0} request.", requestMessage.GetType().Name); var responseMessage = this.RequestCoreAsync(requestMessage, cancellationToken); ErrorUtilities.VerifyProtocol(responseMessage != null, MessagingStrings.ExpectedMessageNotReceived, typeof(IProtocolMessage).Name); Logger.Channel.DebugFormat("Received {0} response.", responseMessage.GetType().Name); this.ProcessIncomingMessageAsync(responseMessage, cancellationToken); return(responseMessage); }
/// <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> /// 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> /// HttpRequestMessage装换未IDirectedProtocolMessage /// </summary> /// <param name="httpRequest"></param> /// <param name="cancellationToken"></param> /// <returns></returns> public IDirectedProtocolMessage ReadFromRequestAsync(HttpRequestMessage httpRequest, CancellationToken cancellationToken) { if (Logger.Channel.IsInfoEnabled() && httpRequest.RequestUri != null) { Logger.Channel.InfoFormat("Scanning incoming request for messages: {0}", httpRequest.RequestUri.AbsoluteUri); } IDirectedProtocolMessage requestMessage = this.ReadFromRequestCoreAsync(httpRequest, cancellationToken); if (requestMessage != null) { Logger.Channel.DebugFormat("Incoming request received: {0}", requestMessage.GetType().Name); var directRequest = requestMessage as IHttpDirectRequest; if (directRequest != null) { foreach (var header in httpRequest.Headers) { directRequest.Headers.Add(header.Key, header.Value); } } this.ProcessIncomingMessageAsync(requestMessage, cancellationToken); } return(requestMessage); }
/// <summary> /// Instantiates the given request message type. /// </summary> /// <param name="messageDescription">The message description.</param> /// <param name="request">The request that resulted in this response.</param> /// <returns>The instantiated message. Never null.</returns> protected virtual IDirectResponseProtocolMessage InstantiateAsResponse(MessageDescription messageDescription, IDirectedProtocolMessage request) { Requires.NotNull(messageDescription, "messageDescription"); Requires.NotNull(request, "request"); Type requestType = request.GetType(); var ctors = this.FindMatchingResponseConstructors(messageDescription, requestType); ConstructorInfo ctor = null; try { ctor = ctors.Single(); } catch (InvalidOperationException) { if (ctors.Any()) { ErrorUtilities.ThrowInternal("More than one matching constructor for request type " + requestType.Name + " and response type " + messageDescription.MessageType.Name); } else { ErrorUtilities.ThrowInternal("Unexpected request message type " + requestType.FullName + " for response type " + messageDescription.MessageType.Name); } } return((IDirectResponseProtocolMessage)ctor.Invoke(new object[] { request })); }
/// <summary> /// Analyzes an incoming request message payload to discover what kind of /// message is embedded in it and returns the type, or null if no match is found. /// </summary> /// <param name="request"> /// The message that was sent as a request that resulted in the response. /// Null on a Consumer site that is receiving an indirect message from the Service Provider. /// </param> /// <param name="fields">The name/value pairs that make up the message payload.</param> /// <returns> /// A newly instantiated <see cref="IProtocolMessage"/>-derived object that this message can /// deserialize to. Null if the request isn't recognized as a valid protocol message. /// </returns> /// <remarks> /// The response messages are: /// UnauthorizedTokenResponse /// AuthorizedTokenResponse /// </remarks> public virtual IDirectResponseProtocolMessage GetNewResponseMessage(IDirectedProtocolMessage request, IDictionary<string, string> fields) { ErrorUtilities.VerifyArgumentNotNull(request, "request"); ErrorUtilities.VerifyArgumentNotNull(fields, "fields"); MessageBase message = null; // All response messages have the oauth_token field. if (!fields.ContainsKey("oauth_token")) { return null; } // All direct message responses should have the oauth_token_secret field. if (!fields.ContainsKey("oauth_token_secret")) { Logger.OAuth.Error("An OAuth message was expected to contain an oauth_token_secret but didn't."); return null; } var unauthorizedTokenRequest = request as UnauthorizedTokenRequest; var authorizedTokenRequest = request as AuthorizedTokenRequest; if (unauthorizedTokenRequest != null) { Protocol protocol = fields.ContainsKey("oauth_callback_confirmed") ? Protocol.V10a : Protocol.V10; message = new UnauthorizedTokenResponse(unauthorizedTokenRequest, protocol.Version); } else if (authorizedTokenRequest != null) { message = new AuthorizedTokenResponse(authorizedTokenRequest); } else { Logger.OAuth.ErrorFormat("Unexpected response message given the request type {0}", request.GetType().Name); throw new ProtocolException(OAuthStrings.InvalidIncomingMessage); } if (message != null) { message.SetAsIncoming(); } return message; }
/// <summary> /// Analyzes an incoming request message payload to discover what kind of /// message is embedded in it and returns the type, or null if no match is found. /// </summary> /// <param name="request"> /// The message that was sent as a request that resulted in the response. /// Null on a Consumer site that is receiving an indirect message from the Service Provider. /// </param> /// <param name="fields">The name/value pairs that make up the message payload.</param> /// <returns> /// A newly instantiated <see cref="IProtocolMessage"/>-derived object that this message can /// deserialize to. Null if the request isn't recognized as a valid protocol message. /// </returns> /// <remarks> /// The response messages are: /// UnauthorizedTokenResponse /// AuthorizedTokenResponse /// </remarks> public virtual IDirectResponseProtocolMessage GetNewResponseMessage(IDirectedProtocolMessage request, IDictionary <string, string> fields) { MessageBase message = null; // All response messages have the oauth_token field. if (!fields.ContainsKey("oauth_token")) { return(null); } // All direct message responses should have the oauth_token_secret field. if (!fields.ContainsKey("oauth_token_secret")) { Logger.OAuth.Error("An OAuth message was expected to contain an oauth_token_secret but didn't."); return(null); } var unauthorizedTokenRequest = request as UnauthorizedTokenRequest; var authorizedTokenRequest = request as AuthorizedTokenRequest; if (unauthorizedTokenRequest != null) { Protocol protocol = fields.ContainsKey("oauth_callback_confirmed") ? Protocol.V10a : Protocol.V10; message = new UnauthorizedTokenResponse(unauthorizedTokenRequest, protocol.Version); } else if (authorizedTokenRequest != null) { message = new AuthorizedTokenResponse(authorizedTokenRequest); } else { Logger.OAuth.ErrorFormat("Unexpected response message given the request type {0}", request.GetType().Name); throw new ProtocolException(OAuthStrings.InvalidIncomingMessage); } if (message != null) { message.SetAsIncoming(); } return(message); }
/// <summary> /// Gets the message type that best fits the given incoming direct response data. /// </summary> /// <param name="request">The request message that prompted the response data.</param> /// <param name="fields">The data of the incoming message.</param> /// <returns> /// The message type that matches the incoming data; or <c>null</c> if no match. /// </returns> /// <exception cref="ProtocolException">May be thrown if the incoming data is ambiguous.</exception> protected virtual MessageDescription GetMessageDescription(IDirectedProtocolMessage request, IDictionary <string, string> fields) { Requires.NotNull(request, "request"); Requires.NotNull(fields, "fields"); var matches = (from responseMessageType in this.responseMessageTypes let message = responseMessageType.Key where message.CheckMessagePartsPassBasicValidation(fields) let ctors = this.FindMatchingResponseConstructors(message, request.GetType()) where ctors.Any() orderby GetDerivationDistance(ctors.First().GetParameters()[0].ParameterType, request.GetType()), CountInCommon(message.Mapping.Keys, fields.Keys) descending, message.Mapping.Count descending select message).CacheGeneratedResults(); var match = matches.FirstOrDefault(); if (match != null) { return(match); } else { // No message type matches the incoming data. return(null); } }
/// <summary> /// Prepares an HTTP request that carries a given message. /// </summary> /// <param name="request">The message to send.</param> /// <returns> /// The <see cref="HttpRequest"/> prepared to send the request. /// </returns> protected override HttpWebRequest CreateHttpRequest(IDirectedProtocolMessage request) { ErrorUtilities.VerifyArgumentNotNull(request, "request"); ErrorUtilities.VerifyArgumentNamed(request.Recipient != null, "request", MessagingStrings.DirectedMessageMissingRecipient); IDirectedProtocolMessage oauthRequest = request as IDirectedProtocolMessage; ErrorUtilities.VerifyArgument(oauthRequest != null, MessagingStrings.UnexpectedType, typeof(IDirectedProtocolMessage), request.GetType()); HttpWebRequest httpRequest; HttpDeliveryMethods transmissionMethod = oauthRequest.HttpMethods; if ((transmissionMethod & HttpDeliveryMethods.AuthorizationHeaderRequest) != 0) { httpRequest = this.InitializeRequestAsAuthHeader(request); } else if ((transmissionMethod & HttpDeliveryMethods.PostRequest) != 0) { httpRequest = this.InitializeRequestAsPost(request); } else if ((transmissionMethod & HttpDeliveryMethods.GetRequest) != 0) { httpRequest = InitializeRequestAsGet(request); } else { throw new NotSupportedException(); } return(httpRequest); }
/// <summary> /// Prepares an HTTP request that carries a given message. /// </summary> /// <param name="request">The message to send.</param> /// <returns> /// The <see cref="HttpRequest"/> prepared to send the request. /// </returns> protected override HttpWebRequest CreateHttpRequest(IDirectedProtocolMessage request) { ErrorUtilities.VerifyArgumentNotNull(request, "request"); ErrorUtilities.VerifyArgumentNamed(request.Recipient != null, "request", MessagingStrings.DirectedMessageMissingRecipient); IDirectedProtocolMessage oauthRequest = request as IDirectedProtocolMessage; ErrorUtilities.VerifyArgument(oauthRequest != null, MessagingStrings.UnexpectedType, typeof(IDirectedProtocolMessage), request.GetType()); HttpWebRequest httpRequest; HttpDeliveryMethods transmissionMethod = oauthRequest.HttpMethods; if ((transmissionMethod & HttpDeliveryMethods.AuthorizationHeaderRequest) != 0) { httpRequest = this.InitializeRequestAsAuthHeader(request); } else if ((transmissionMethod & HttpDeliveryMethods.PostRequest) != 0) { httpRequest = this.InitializeRequestAsPost(request); } else if ((transmissionMethod & HttpDeliveryMethods.GetRequest) != 0) { httpRequest = InitializeRequestAsGet(request); } else { throw new NotSupportedException(); } return httpRequest; }
public static bool TryReadFromRequest <TRequest>(this Channel chan, Request httpRequest, out TRequest request) where TRequest : class, IProtocolMessage { if (httpRequest == null) { throw new ArgumentNullException("httpRequest"); } Contract.Ensures(Contract.Result <bool>() == (Contract.ValueAtReturn <TRequest>(out request) != null)); IProtocolMessage untypedRequest = null; if (Logger.IsInfoEnabled && httpRequest.Url != null) { Logger.InfoFormat("Scanning incoming request for messages: {0}", httpRequest.Url.ToString()); } IDirectedProtocolMessage requestMessage = null; Contract.Assume(httpRequest.Form != null && httpRequest.Query != null); var fields = httpRequest.Form.ToDictionary(); if (fields.Count == 0 && httpRequest.Method != "POST") // OpenID 2.0 section 4.1.2 { fields = ((IDictionary <string, object>)(DynamicDictionary) httpRequest.Query).ToDictionary(kvp => kvp.Key, kvp => kvp.Value.ToString()); } MessageReceivingEndpoint recipient = null; try { HttpDeliveryMethods method; Enum.TryParse <HttpDeliveryMethods>(httpRequest.Method + "Request", true, out method); recipient = new MessageReceivingEndpoint(httpRequest.Url.SiteBase, method); } catch (ArgumentException ex) { Logger.WarnFormat("Unrecognized HTTP request: {0}", ex); requestMessage = null; } if (recipient != null) { requestMessage = (IDirectedProtocolMessage)Receive(chan, fields, recipient); } if (requestMessage != null) { Logger.DebugFormat("Incoming request received: {0}", requestMessage.GetType().Name); var directRequest = requestMessage as IHttpDirectRequest; if (directRequest != null) { foreach (string header in httpRequest.Headers.Keys) { directRequest.Headers[header] = httpRequest.Headers[header].ToString(); } } ProcessIncomingMessage(chan, requestMessage); untypedRequest = requestMessage; } if (untypedRequest == null) { request = null; return(false); } request = untypedRequest as TRequest; return(true); }
/// <summary> /// Instantiates the given request message type. /// </summary> /// <param name="messageDescription">The message description.</param> /// <param name="request">The request that resulted in this response.</param> /// <returns>The instantiated message. Never null.</returns> protected virtual IDirectResponseProtocolMessage InstantiateAsResponse(MessageDescription messageDescription, IDirectedProtocolMessage request) { Contract.Requires<ArgumentNullException>(messageDescription != null); Contract.Requires<ArgumentNullException>(request != null); Contract.Ensures(Contract.Result<IDirectResponseProtocolMessage>() != null); Type requestType = request.GetType(); var ctors = this.FindMatchingResponseConstructors(messageDescription, requestType); ConstructorInfo ctor = null; try { ctor = ctors.Single(); } catch (InvalidOperationException) { if (ctors.Any()) { ErrorUtilities.ThrowInternal("More than one matching constructor for request type " + requestType.Name + " and response type " + messageDescription.MessageType.Name); } else { ErrorUtilities.ThrowInternal("Unexpected request message type " + requestType.FullName + " for response type " + messageDescription.MessageType.Name); } } return (IDirectResponseProtocolMessage)ctor.Invoke(new object[] { request }); }
/// <summary> /// Gets the message type that best fits the given incoming direct response data. /// </summary> /// <param name="request">The request message that prompted the response data.</param> /// <param name="fields">The data of the incoming message.</param> /// <returns> /// The message type that matches the incoming data; or <c>null</c> if no match. /// </returns> /// <exception cref="ProtocolException">May be thrown if the incoming data is ambiguous.</exception> protected virtual MessageDescription GetMessageDescription(IDirectedProtocolMessage request, IDictionary<string, string> fields) { Contract.Requires<ArgumentNullException>(request != null); Contract.Requires<ArgumentNullException>(fields != null); var matches = (from responseMessageType in this.responseMessageTypes let message = responseMessageType.Key where message.CheckMessagePartsPassBasicValidation(fields) let ctors = this.FindMatchingResponseConstructors(message, request.GetType()) where ctors.Any() orderby GetDerivationDistance(ctors.First().GetParameters()[0].ParameterType, request.GetType()), CountInCommon(message.Mapping.Keys, fields.Keys) descending, message.Mapping.Count descending select message).CacheGeneratedResults(); var match = matches.FirstOrDefault(); if (match != null) { if (Logger.Messaging.IsWarnEnabled && matches.Count() > 1) { Logger.Messaging.WarnFormat( "Multiple message types seemed to fit the incoming data: {0}", matches.ToStringDeferred()); } return match; } else { // No message type matches the incoming data. return null; } }
protected virtual MessageDescription GetMessageDescription(IDirectedProtocolMessage request, IDictionary <string, string> fields) { var matches = (from responseMessageType in this.responseMessageTypes let messge = responseMessageType.Key where messge.CheckMessagePartsPassBasicValidation(fields) let ctors = this.FindMatchingResponseConstructors(messge, request.GetType()) where ctors.Any() orderby GetDerivationDistance(ctors.First().GetParameters()[0].ParameterType, request.GetType()), CountInCommon(messge.Mapping.Keys, fields.Keys) descending, messge.Mapping.Count descending select messge).CacheGeneratedResults(); var match = matches.FirstOrDefault(); if (match != null) { if (Logger.Messaging.IsWarnEnabled() && matches.Count() > 1) { Logger.Messaging.WarnFormat( "Multiple message types seemed to fit the incoming data: {0}", matches.ToStringDeferred()); } return(match); } else { return(null); } }