//----------------------------------------------------------------------- // // Copyright (c) Outercurve Foundation. All rights reserved. // //----------------------------------------------------------------------- namespace DotNetOpenAuth.Messaging { using System; using System.Collections.Specialized; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Contracts; using System.Globalization; using System.IO; using System.Net; using System.Net.Mime; using System.ServiceModel.Channels; using System.Web; /// /// A property store of details of an incoming HTTP request. /// /// /// This serves a very similar purpose to , except that /// ASP.NET does not let us fully initialize that class, so we have to write one /// of our one. /// public class HttpRequestInfo : HttpRequestBase { /// /// The HTTP verb in the request. /// private readonly string httpMethod; /// /// The full request URL. /// private readonly Uri requestUri; /// /// The HTTP headers. /// private readonly NameValueCollection headers; /// /// The variables defined in the query part of the URL. /// private readonly NameValueCollection queryString; /// /// The POSTed form variables. /// private readonly NameValueCollection form; /// /// The server variables collection. /// private readonly NameValueCollection serverVariables; /// /// Initializes a new instance of the class. /// /// The request. /// The request URI. internal HttpRequestInfo(HttpRequestMessageProperty request, Uri requestUri) { Requires.NotNull(request, "request"); Requires.NotNull(requestUri, "requestUri"); this.httpMethod = request.Method; this.headers = request.Headers; this.requestUri = requestUri; this.form = new NameValueCollection(); this.queryString = HttpUtility.ParseQueryString(requestUri.Query); this.serverVariables = new NameValueCollection(); Reporting.RecordRequestStatistics(this); } /// /// Initializes a new instance of the class. /// /// The HTTP method. /// The request URI. /// The form variables. /// The HTTP headers. internal HttpRequestInfo(string httpMethod, Uri requestUri, NameValueCollection form = null, NameValueCollection headers = null) { Requires.NotNullOrEmpty(httpMethod, "httpMethod"); Requires.NotNull(requestUri, "requestUri"); this.httpMethod = httpMethod; this.requestUri = requestUri; this.form = form ?? new NameValueCollection(); this.queryString = HttpUtility.ParseQueryString(requestUri.Query); this.headers = headers ?? new NameValueCollection(); this.serverVariables = new NameValueCollection(); } /// /// Initializes a new instance of the class. /// /// Details on the incoming HTTP request. internal HttpRequestInfo(HttpListenerRequest listenerRequest) { Requires.NotNull(listenerRequest, "listenerRequest"); this.httpMethod = listenerRequest.HttpMethod; this.requestUri = listenerRequest.Url; this.queryString = listenerRequest.QueryString; this.headers = listenerRequest.Headers; this.form = ParseFormData(listenerRequest.HttpMethod, listenerRequest.Headers, listenerRequest.InputStream); this.serverVariables = new NameValueCollection(); Reporting.RecordRequestStatistics(this); } /// /// Initializes a new instance of the class. /// /// The HTTP method. /// The request URI. /// The headers. /// The input stream. internal HttpRequestInfo(string httpMethod, Uri requestUri, NameValueCollection headers, Stream inputStream) { Requires.NotNullOrEmpty(httpMethod, "httpMethod"); Requires.NotNull(requestUri, "requestUri"); this.httpMethod = httpMethod; this.requestUri = requestUri; this.headers = headers; this.queryString = HttpUtility.ParseQueryString(requestUri.Query); this.form = ParseFormData(httpMethod, headers, inputStream); this.serverVariables = new NameValueCollection(); Reporting.RecordRequestStatistics(this); } /// /// Gets the HTTP method. /// public override string HttpMethod { get { return this.httpMethod; } } /// /// Gets the headers. /// public override NameValueCollection Headers { get { return this.headers; } } /// /// Gets the URL. /// public override Uri Url { get { return this.requestUri; } } /// /// Gets the raw URL. /// public override string RawUrl { get { return this.requestUri.AbsolutePath + this.requestUri.Query; } } /// /// Gets the form. /// public override NameValueCollection Form { get { return this.form; } } /// /// Gets the query string. /// public override NameValueCollection QueryString { get { return this.queryString; } } /// /// Gets the server variables. /// public override NameValueCollection ServerVariables { get { return this.serverVariables; } } /// /// Creates an instance that describes the specified HTTP request. /// /// The request. /// The request URI. /// An instance of . public static HttpRequestBase Create(HttpRequestMessageProperty request, Uri requestUri) { return new HttpRequestInfo(request, requestUri); } /// /// Creates an instance that describes the specified HTTP request. /// /// The listener request. /// An instance of . public static HttpRequestBase Create(HttpListenerRequest listenerRequest) { return new HttpRequestInfo(listenerRequest); } /// /// Creates an instance that describes the specified HTTP request. /// /// The HTTP method. /// The request URI. /// The form variables. /// The HTTP headers. /// An instance of . public static HttpRequestBase Create(string httpMethod, Uri requestUri, NameValueCollection form = null, NameValueCollection headers = null) { return new HttpRequestInfo(httpMethod, requestUri, form, headers); } /// /// Creates an instance that describes the specified HTTP request. /// /// The HTTP method. /// The request URI. /// The headers. /// The input stream. /// An instance of . public static HttpRequestBase Create(string httpMethod, Uri requestUri, NameValueCollection headers, Stream inputStream) { return new HttpRequestInfo(httpMethod, requestUri, headers, inputStream); } /// /// Reads name=value pairs from the POSTed form entity when the HTTP headers indicate that that is the payload of the entity. /// /// The HTTP method. /// The headers. /// The input stream. /// The non-null collection of form variables. private static NameValueCollection ParseFormData(string httpMethod, NameValueCollection headers, Stream inputStream) { Requires.NotNullOrEmpty(httpMethod, "httpMethod"); Requires.NotNull(headers, "headers"); ContentType contentType = string.IsNullOrEmpty(headers[HttpRequestHeaders.ContentType]) ? null : new ContentType(headers[HttpRequestHeaders.ContentType]); if (inputStream != null && httpMethod == "POST" && contentType != null && string.Equals(contentType.MediaType, Channel.HttpFormUrlEncoded, StringComparison.Ordinal)) { var reader = new StreamReader(inputStream); long originalPosition = 0; if (inputStream.CanSeek) { originalPosition = inputStream.Position; } string postEntity = reader.ReadToEnd(); if (inputStream.CanSeek) { inputStream.Seek(originalPosition, SeekOrigin.Begin); } return HttpUtility.ParseQueryString(postEntity); } return new NameValueCollection(); } } }