HttpRequestContext.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / Channels / HttpRequestContext.cs / 2 / HttpRequestContext.cs

                            //---------------------------------------------------------------------------- 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//---------------------------------------------------------------------------
namespace System.ServiceModel.Channels
{ 
    using System;
    using System.ServiceModel; 
    using System.ServiceModel.Activation; 
    using System.IO;
    using System.Net; 
    using System.IdentityModel.Claims;
    using System.IdentityModel.Policy;
    using System.ServiceModel.Security;
    using System.Text; 
    using System.Threading;
    using System.Web; 
    using System.Xml; 
    using System.ServiceModel.Diagnostics;
 
    abstract class HttpRequestContext : RequestContextBase
    {
        HttpOutput httpOutput;
        HttpInput httpInput; 
        HttpChannelListener listener;
        SecurityMessageProperty securityProperty; 
 
        protected HttpRequestContext(HttpChannelListener listener, Message requestMessage)
            : base(requestMessage, listener.InternalCloseTimeout, listener.InternalSendTimeout) 
        {
            this.listener = listener;
        }
 
        public bool KeepAliveEnabled
        { 
            get 
            {
                return listener.KeepAliveEnabled; 
            }
        }

        protected HttpChannelListener Listener 
        {
            get { return this.listener; } 
        } 

        internal static HttpRequestContext CreateContext(HttpChannelListener listener, HttpListenerContext listenerContext) 
        {
            return new ListenerHttpContext(listener, listenerContext);
        }
 
        internal static HttpRequestContext CreateContext(HttpChannelListener listener, HostedHttpRequestAsyncResult result)
        { 
            return new HostedHttpContext(listener, result); 
        }
 
        protected HttpInput HttpInput
        {
            get
            { 
                if (httpInput == null)
                { 
                    httpInput = GetHttpInput(); 
                }
                return httpInput; 
            }
        }

        public abstract string HttpMethod { get; } 
        protected abstract SecurityMessageProperty OnProcessAuthentication();
        protected abstract HttpOutput GetHttpOutput(Message message); 
        protected abstract HttpInput GetHttpInput(); 

        protected override void OnAbort() 
        {
            if (this.httpOutput != null)
            {
                this.httpOutput.Abort(HttpAbortReason.Aborted); 
            }
        } 
 
        protected override void OnClose(TimeSpan timeout)
        { 
            if (this.httpOutput != null)
            {
                this.httpOutput.Close();
            } 
        }
 
        void SetRequestMessage(Message message, Exception requestException) 
        {
            if (requestException != null) 
            {
                base.SetRequestMessage(requestException);
                message.Close();
            } 
            else
            { 
                message.Properties.Security = (this.securityProperty != null) ? (SecurityMessageProperty)this.securityProperty.CreateCopy() : null; 
                base.SetRequestMessage(message);
            } 
        }

        public void CreateMessage()
        { 
            HttpInput httpInput = this.HttpInput;
            Message message; 
            Exception requestException; 
            message = httpInput.ParseIncomingMessage(out requestException);
 
            if ((message == null) && (requestException == null))
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new ProtocolException(SR.GetString(SR.MessageXmlProtocolError), 
                    new XmlException(SR.GetString(SR.MessageIsEmpty))));
            } 
 
            this.SetRequestMessage(message, requestException);
        } 

        protected abstract HttpStatusCode ValidateAuthentication();

        bool PrepareReply(ref Message message) 
        {
            // null means we're done 
            if (message == null) 
            {
                message = CreateAckMessage(HttpStatusCode.Accepted, string.Empty); 
            }

            if (!listener.ManualAddressing)
            { 
                if (message.Version.Addressing == AddressingVersion.WSAddressingAugust2004)
                { 
                    message.Headers.To = message.Version.Addressing.AnonymousUri; 
                }
                else if (message.Version.Addressing == AddressingVersion.WSAddressing10 
                    || message.Version.Addressing == AddressingVersion.None)
                {
                    message.Headers.To = null;
                } 
                else
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                        new ProtocolException(SR.GetString(SR.AddressingVersionNotSupported, message.Version.Addressing)));
                } 
            }

            message.Properties.AllowOutputBatching = false;
            this.httpOutput = GetHttpOutput(message); 

            // now see if the output should be closed after we reply 
            HttpDelayedAcceptStream requestStream = HttpInput.InputStream as HttpDelayedAcceptStream; 
            if (requestStream != null && TransferModeHelper.IsRequestStreamed(listener.TransferMode)
                && requestStream.EnableDelayedAccept(this.httpOutput)) 
            {
                return false;
            }
 
            return true;
        } 
 
        protected override void OnReply(Message message, TimeSpan timeout)
        { 
            TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
            bool closeOutputAfterReply = PrepareReply(ref message);
            ThreadTrace.Trace("Begin sending http reply");
            httpOutput.Send(timeoutHelper.RemainingTime()); 
            ThreadTrace.Trace("End sending http reply");
            if (closeOutputAfterReply) 
            { 
                httpOutput.Close();
            } 
        }

        protected override IAsyncResult OnBeginReply(
            Message message, TimeSpan timeout, AsyncCallback callback, object state) 
        {
            return new ReplyAsyncResult(this, message, timeout, callback, state); 
        } 

        protected override void OnEndReply(IAsyncResult result) 
        {
            ReplyAsyncResult.End(result);
        }
 
        class ReplyAsyncResult : AsyncResult
        { 
            static AsyncCallback onSend; 
            HttpRequestContext context;
            bool closeOutputAfterReply; 

            public ReplyAsyncResult(HttpRequestContext context, Message message, TimeSpan timeout, AsyncCallback callback, object state)
                : base(callback, state)
            { 
                this.context = context;
                this.closeOutputAfterReply = context.PrepareReply(ref message); 
 
                ThreadTrace.Trace("Begin sending http reply");
                if (onSend == null) 
                {
                    onSend = DiagnosticUtility.ThunkAsyncCallback(new AsyncCallback(OnSend));
                }
                IAsyncResult result = context.httpOutput.BeginSend(timeout, onSend, this); 
                if (!result.CompletedSynchronously)
                { 
                    return; 
                }
 
                HandleEndSend(result);
                base.Complete(true);
            }
 
            public static void End(IAsyncResult result)
            { 
                AsyncResult.End(result); 
            }
 
            void HandleEndSend(IAsyncResult result)
            {
                context.httpOutput.EndSend(result);
                ThreadTrace.Trace("End sending http reply"); 

                if (this.closeOutputAfterReply) 
                { 
                    context.httpOutput.Close();
                } 
            }

            static void OnSend(IAsyncResult result)
            { 
                if (result.CompletedSynchronously)
                { 
                    return; 
                }
 
                ReplyAsyncResult thisPtr = (ReplyAsyncResult)result.AsyncState;
                Exception completionException = null;
                try
                { 
                    thisPtr.HandleEndSend(result);
                } 
#pragma warning suppress 56500 // covered by FxCOP 
                catch (Exception e)
                { 
                    if (DiagnosticUtility.IsFatal(e))
                    {
                        throw;
                    } 
                    completionException = e;
                } 
 
                thisPtr.Complete(false, completionException);
            } 
        }

        public bool ProcessAuthentication()
        { 
            HttpStatusCode statusCode = ValidateAuthentication();
 
            if (statusCode == HttpStatusCode.OK) 
            {
                bool authenticationSucceeded = false; 
                try
                {
                    this.securityProperty = OnProcessAuthentication();
                    authenticationSucceeded = true; 
                    return true;
                } 
                finally 
                {
                    if (!authenticationSucceeded) 
                    {
                        SendResponseAndClose(HttpStatusCode.Forbidden);
                    }
                } 
            }
            else 
            { 
                SendResponseAndClose(statusCode);
                return false; 
            }
        }

        internal void SendResponseAndClose(HttpStatusCode statusCode) 
        {
            SendResponseAndClose(statusCode, string.Empty); 
        } 

        internal void SendResponseAndClose(HttpStatusCode statusCode, string statusDescription) 
        {
            if (ReplyInitiated)
            {
                this.Close(); 
                return;
            } 
 
            using (Message ackMessage = CreateAckMessage(statusCode, statusDescription))
            { 
                this.Reply(ackMessage);
            }

            this.Close(); 
        }
 
        Message CreateAckMessage(HttpStatusCode statusCode, string statusDescription) 
        {
            Message ackMessage = new NullMessage(); 
            HttpResponseMessageProperty httpResponseProperty = new HttpResponseMessageProperty();
            httpResponseProperty.StatusCode = statusCode;
            httpResponseProperty.SuppressEntityBody = true;
            if (statusDescription.Length > 0) 
            {
                httpResponseProperty.StatusDescription = statusDescription; 
            } 

            ackMessage.Properties.Add(HttpResponseMessageProperty.Name, httpResponseProperty); 

            return ackMessage;
        }
 
        class ListenerHttpContext : HttpRequestContext
        { 
            HttpListenerContext listenerContext; 

            public ListenerHttpContext(HttpChannelListener listener, 
                HttpListenerContext listenerContext)
                : base(listener, null)
            {
                this.listenerContext = listenerContext; 
            }
 
            public override string HttpMethod 
            {
                get { return listenerContext.Request.HttpMethod; } 
            }

            protected override HttpInput GetHttpInput()
            { 
                return new ListenerContextHttpInput(this);
            } 
 
            protected override HttpOutput GetHttpOutput(Message message)
            { 
                // work around http.sys keep alive bug with chunked requests, see MB 49676, this is fixed in Vista
                if (listenerContext.Request.ContentLength64 == -1 && !OSEnvironmentHelper.IsVistaOrGreater)
                {
                    listenerContext.Response.KeepAlive = false; 
                }
                else 
                { 
                    listenerContext.Response.KeepAlive = listener.KeepAliveEnabled;
                } 

                return HttpOutput.CreateHttpOutput(listenerContext.Response, Listener, message);
            }
 
            protected override SecurityMessageProperty OnProcessAuthentication()
            { 
                return Listener.ProcessAuthentication(listenerContext); 
            }
 
            protected override HttpStatusCode ValidateAuthentication()
            {
                return Listener.ValidateAuthentication(listenerContext);
            } 

            protected override void OnAbort() 
            { 
                listenerContext.Response.Abort();
            } 

            protected override void OnClose(TimeSpan timeout)
            {
                TimeoutHelper timeoutHelper = new TimeoutHelper(timeout); 
                base.OnClose(timeoutHelper.RemainingTime());
                try 
                { 
                    listenerContext.Response.Close();
                } 
                catch (HttpListenerException listenerException)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                        HttpChannelUtilities.CreateCommunicationException(listenerException)); 
                }
            } 
 
            class ListenerContextHttpInput : HttpInput
            { 
                ListenerHttpContext listenerHttpContext;
                string cachedContentType; // accessing the header in System.Net involves a native transition
                byte[] preReadBuffer;
 
                public ListenerContextHttpInput(ListenerHttpContext listenerHttpContext)
                    : base(listenerHttpContext.Listener, true) 
                { 
                    this.listenerHttpContext = listenerHttpContext;
                    if (this.listenerHttpContext.listenerContext.Request.ContentLength64 == -1) 
                    {
                        this.preReadBuffer = new byte[1];
                        if (this.listenerHttpContext.listenerContext.Request.InputStream.Read(preReadBuffer, 0, 1) == 0)
                        { 
                            this.preReadBuffer = null;
                        } 
                    } 
                }
 
                public override long ContentLength
                {
                    get
                    { 
                        return this.listenerHttpContext.listenerContext.Request.ContentLength64;
                    } 
                } 

                protected override string ContentType 
                {
                    get
                    {
                        if (this.cachedContentType == null) 
                        {
                            this.cachedContentType = this.listenerHttpContext.listenerContext.Request.ContentType; 
                        } 

                        return this.cachedContentType; 
                    }
                }

                protected override bool HasContent 
                {
                    get { return (this.preReadBuffer != null || this.ContentLength > 0); } 
                } 

                protected override string SoapActionHeader 
                {
                    get
                    {
                        return this.listenerHttpContext.listenerContext.Request.Headers["SOAPAction"]; 
                    }
                } 
 
                protected override void AddProperties(Message message)
                { 
                    HttpRequestMessageProperty requestProperty = new HttpRequestMessageProperty(this.listenerHttpContext.listenerContext.Request);
                    requestProperty.Method = this.listenerHttpContext.listenerContext.Request.HttpMethod;

                    // Uri.Query always includes the '?' 
                    if (this.listenerHttpContext.listenerContext.Request.Url.Query.Length > 1)
                    { 
                        requestProperty.QueryString = this.listenerHttpContext.listenerContext.Request.Url.Query.Substring(1); 
                    }
 
                    message.Properties.Add(HttpRequestMessageProperty.Name, requestProperty);
                    message.Properties.Via = this.listenerHttpContext.listenerContext.Request.Url;

                    RemoteEndpointMessageProperty remoteEndpointProperty = new RemoteEndpointMessageProperty(this.listenerHttpContext.listenerContext.Request.RemoteEndPoint); 
                    message.Properties.Add(RemoteEndpointMessageProperty.Name, remoteEndpointProperty);
                } 
 
                protected override Stream GetInputStream()
                { 
                    if (this.preReadBuffer != null)
                    {
                        return new ListenerContextInputStream(listenerHttpContext, preReadBuffer);
                    } 
                    else
                    { 
                        return new ListenerContextInputStream(listenerHttpContext); 
                    }
                } 

                class ListenerContextInputStream : HttpDelayedAcceptStream
                {
                    public ListenerContextInputStream(ListenerHttpContext listenerHttpContext) 
                        : base(listenerHttpContext.listenerContext.Request.InputStream)
                    { 
                    } 

                    public ListenerContextInputStream(ListenerHttpContext listenerHttpContext, byte[] preReadBuffer) 
                        : base(new PreReadStream(listenerHttpContext.listenerContext.Request.InputStream, preReadBuffer))
                    {
                    }
 
                    public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
                    { 
                        try 
                        {
                            return base.BeginRead(buffer, offset, count, callback, state); 
                        }
                        catch (HttpListenerException listenerException)
                        {
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                                HttpChannelUtilities.CreateCommunicationException(listenerException));
                        } 
                    } 

                    public override int EndRead(IAsyncResult result) 
                    {
                        try
                        {
                            return base.EndRead(result); 
                        }
                        catch (HttpListenerException listenerException) 
                        { 
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                                HttpChannelUtilities.CreateCommunicationException(listenerException)); 
                        }
                    }

                    public override int Read(byte[] buffer, int offset, int count) 
                    {
                        try 
                        { 
                            return base.Read(buffer, offset, count);
                        } 
                        catch (HttpListenerException listenerException)
                        {
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                                HttpChannelUtilities.CreateCommunicationException(listenerException)); 
                        }
                    } 
 
                    public override int ReadByte()
                    { 
                        try
                        {
                            return base.ReadByte();
                        } 
                        catch (HttpListenerException listenerException)
                        { 
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                                HttpChannelUtilities.CreateCommunicationException(listenerException));
                        } 
                    }
                }
            }
        } 
    }
 
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.


                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK