HTTPRemotingHandler.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / clr / src / ManagedLibraries / Remoting / Channels / HTTP / HTTPRemotingHandler.cs / 1305376 / HTTPRemotingHandler.cs

                            // ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
//==========================================================================
//  File:       HTTPRemotingHandler.cs 
// 
//  Summary:    Implements an ASP+ handler that forwards requests to the
//              the remoting HTTP Channel. 
//
//  Classes:    Derived from IHttpHandler
//
// 
//=========================================================================
 
using System; 
using System.DirectoryServices;
using System.IO; 
using System.Net;
using System.Text;
using System.Threading;
using System.Reflection; 
using System.Collections;
using System.Runtime.Remoting; 
using System.Runtime.Remoting.Channels; 
using System.Runtime.Remoting.Messaging;
using System.Diagnostics; 
using System.Web;
using System.Web.UI;
using System.Runtime.Remoting.MetadataServices;
using System.Globalization; 
using System.Collections.Specialized;
 
namespace System.Runtime.Remoting.Channels.Http 
{
 
    public class HttpRemotingHandler : IHttpHandler
    {
        //Handler Specific
 
        private static String ApplicationConfigurationFile = "web.config";
        private static bool bLoadedConfiguration = false; 
 
        private static HttpHandlerTransportSink s_transportSink = null; // transport sink
 

        // If an exception occurs while we are configuring the app domain, it is not possible
        // to recover since remoting is in an indeterminate state, so we will return that
        // exception every time. 
        private static Exception s_fatalException = null;
 
 
        public HttpRemotingHandler()
        { 
        }

        /// 
        public HttpRemotingHandler(Type type, Object srvID) 
        {
        } 
 
        //
        // Process the ASP+ Request 
        //
        public void ProcessRequest(HttpContext context)
        {
            InternalProcessRequest(context); 
        }
 
        // 
        // Internal
        // 
        // Transform the ASP+ Request and Response Structures in
        // Channel Structures:
        // ** Request.ServerVariables
        // ** Request.InputStream 
        // ** Response.Headers
        // 
        // This is needed to reduce the between dependency COR Channels 
        // and ASP+
        // 

        private void InternalProcessRequest(HttpContext context)
        {
            try 
            {
                HttpRequest httpRequest = context.Request; 
 
                // check if have previously loaded configuration
                if (!bLoadedConfiguration) 
                {
                    // locking a random static variable, so we can lock the class
                    lock(HttpRemotingHandler.ApplicationConfigurationFile)
                    { 
                        if (!bLoadedConfiguration)
                        { 
                            // Initialize IIS information 
                            IisHelper.Initialize();
 
                            // set application name
                            if (RemotingConfiguration.ApplicationName == null)
                                RemotingConfiguration.ApplicationName = httpRequest.ApplicationPath;
 
                            String filename = String.Concat(httpRequest.PhysicalApplicationPath,
                                                            ApplicationConfigurationFile); 
 
                            if (File.Exists(filename))
                            { 
                                try
                                {
                                    RemotingConfiguration.Configure(filename, false/*enableSecurity*/);
                                } 
                                catch (Exception e)
                                { 
                                    s_fatalException = e; 
                                    WriteException(context, e);
                                    return; 
                                }
                            }

                            try 
                            {
                                // do a search for a registered channel that wants to listen 
                                IChannelReceiverHook httpChannel = null; 
                                IChannel[] channels = ChannelServices.RegisteredChannels;
                                foreach (IChannel channel in channels) 
                                {
                                    IChannelReceiverHook hook = channel as IChannelReceiverHook;
                                    if (hook != null)
                                    { 
                                        if (String.Compare(hook.ChannelScheme, "http", StringComparison.OrdinalIgnoreCase) == 0)
                                        { 
                                            if (hook.WantsToListen) 
                                            {
                                                httpChannel = hook; 
                                                break;
                                            }
                                        }
                                    } 
                                }
 
                                if (httpChannel == null) 
                                {
                                    // No http channel that was listening found. 
                                    // Create a new channel.
                                    HttpChannel newHttpChannel = new HttpChannel();
                                    ChannelServices.RegisterChannel(newHttpChannel, false/*enableSecurity*/);
                                    httpChannel = newHttpChannel; 
                                }
 
                                String scheme = null; 
                                if (IisHelper.IsSslRequired)
                                    scheme = "https"; 
                                else
                                    scheme = "http";

                                String hookChannelUri = 
                                    scheme + "://" + CoreChannel.GetMachineIp();
 
                                int port = context.Request.Url.Port; 
                                String restOfUri = ":" + port + "/" + RemotingConfiguration.ApplicationName;
                                hookChannelUri += restOfUri; 

                                // add hook uri for this channel
                                httpChannel.AddHookChannelUri(hookChannelUri);
 
                                // If it uses ChannelDataStore, re-retrieve updated url in case it was updated.
                                ChannelDataStore cds = ((IChannelReceiver)httpChannel).ChannelData as ChannelDataStore; 
                                if (cds != null) 
                                    hookChannelUri = cds.ChannelUris[0];
 
                                IisHelper.ApplicationUrl = hookChannelUri;

                                // This is a hack to refresh the channel data.
                                //   In V-Next, we will add a ChannelServices.RefreshChannelData() api. 
                                ChannelServices.UnregisterChannel(null);
 
                                s_transportSink = new HttpHandlerTransportSink(httpChannel.ChannelSinkChain); 
                            }
                            catch (Exception e) 
                            {
                                s_fatalException = e;
                                WriteException(context, e);
                                return; 
                            }
                            bLoadedConfiguration = true; 
                        } 
                    }
                } 

                if (s_fatalException == null)
                {
                    if (!CanServiceRequest(context)) 
                        WriteException(context, new RemotingException(CoreChannel.GetResourceString("Remoting_ChnlSink_UriNotPublished")));
                    else 
                        s_transportSink.HandleRequest(context); 
                }
                else 
                    WriteException(context, s_fatalException);
            }
            catch (Exception e)
            { 
                WriteException(context, e);
            } 
        } // InternalProcessRequest 

        public bool IsReusable { get { return true; } } 

        string ComposeContentType(string contentType, Encoding encoding) {
            if (encoding != null) {
                StringBuilder sb = new StringBuilder(contentType); 
                sb.Append("; charset=");
                sb.Append(encoding.WebName); 
                return sb.ToString(); 
            }
            else 
                return contentType;
        }

        bool CanServiceRequest(HttpContext context) { 
            //Need to get the object uri first (cannot have query string)
            string requestUri = GetRequestUriForCurrentRequest(context); 
            string objectUri = HttpChannelHelper.GetObjectUriFromRequestUri(requestUri); 
            context.Items["__requestUri"] = requestUri;
 
            if (String.Compare(context.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase) != 0) {
                //If the request backed by an existing object
                if (RemotingServices.GetServerTypeForUri(requestUri) != null)
                    return true; 
            }
            else { 
                if (context.Request.QueryString.Count != 1) 
                    return false;
 
                string[] values =  context.Request.QueryString.GetValues(0);
                if (values.Length != 1 || String.Compare(values[0], "wsdl", StringComparison.OrdinalIgnoreCase) != 0)
                    return false;
 
                //If the request specifically asks for the wildcard
                if (String.Compare(objectUri, "RemoteApplicationMetadata.rem", StringComparison.OrdinalIgnoreCase) == 0) 
                    return true; 

                // find last index of ? 
                int index = requestUri.LastIndexOf('?');
                if (index != -1)
                    requestUri =  requestUri.Substring(0, index);
 
                //If the request backed by an existing object
                if (RemotingServices.GetServerTypeForUri(requestUri) != null) 
                    return true; 
            }
 
            //If the request is backed by an existing file on disk it should be serviced
            if (File.Exists(context.Request.PhysicalPath))
                return true;
 
            return false;
        } 
 
        string GetRequestUriForCurrentRequest(HttpContext context) {
            // we need to pull off any http specific data plus the application v-dir name 
            String rawUrl = context.Request.RawUrl;
            // here's where we pull off channel info
            String channelUri;
            String requestUri; 
            channelUri = HttpChannelHelper.ParseURL(rawUrl, out requestUri);
            if (channelUri == null) 
                requestUri = rawUrl; 

            // here's where we pull off the application v-dir name 
            String appName = RemotingConfiguration.ApplicationName;
            if (appName != null && appName.Length > 0 && requestUri.Length > appName.Length)
                //  "/appname" should always be in front, otherwise we wouldn't
                //   be in this handler. 
                requestUri = requestUri.Substring(appName.Length + 1);
 
            return requestUri; 
        }
 
        string GenerateFaultString(HttpContext context, Exception e) {
            //If the user has specified it's a development server (versus a production server) in ASP.NET config,
            //then we should just return e.ToString instead of extracting the list of messages.
            if (!CustomErrorsEnabled(context)) 
                return e.ToString();
            else { 
                return CoreChannel.GetResourceString("Remoting_InternalError"); 
            }
        } 

        void WriteException(HttpContext context, Exception e) {
            InternalRemotingServices.RemotingTrace("HttpHandler: Exception thrown...\n");
            InternalRemotingServices.RemotingTrace(e.StackTrace); 

            Stream outputStream = context.Response.OutputStream; 
            context.Response.Clear(); 
            context.Response.ClearHeaders();
            context.Response.ContentType = ComposeContentType("text/plain", Encoding.UTF8); 
            context.Response.StatusCode = (int) HttpStatusCode.InternalServerError;
            context.Response.StatusDescription = CoreChannel.GetResourceString("Remoting_InternalError");
            StreamWriter writer = new StreamWriter(outputStream, new UTF8Encoding(false));
            writer.WriteLine(GenerateFaultString(context, e)); 
            writer.Flush();
        } 
 
        internal static bool IsLocal(HttpContext context) {
            string localAddress = context.Request.ServerVariables["LOCAL_ADDR"]; 
            string remoteAddress = context.Request.UserHostAddress;
            return (context.Request.Url.IsLoopback || (localAddress != null && remoteAddress != null && localAddress == remoteAddress));
        }
 
        internal static bool CustomErrorsEnabled(HttpContext context) {
            try { 
                if (!context.IsCustomErrorEnabled) 
                    return false;
 
                return RemotingConfiguration.CustomErrorsEnabled(IsLocal(context));
            }
            catch {
                return true; 
            }
        } 
 
    } // HttpRemotingHandler
 
    public class HttpRemotingHandlerFactory : IHttpHandlerFactory
    {
        internal object _webServicesFactory = null;
        internal static Type s_webServicesFactoryType = null; 
        // REMACT: internal static Type s_remActType = null;
 
        internal static Object s_configLock = new Object(); 

        internal static Hashtable s_registeredDynamicTypeTable = Hashtable.Synchronized(new Hashtable()); 


        void DumpRequest(HttpContext context)
        { 
            HttpRequest request = context.Request;
            InternalRemotingServices.DebugOutChnl("Process Request called."); 
            InternalRemotingServices.DebugOutChnl("Path = " + request.Path); 
            InternalRemotingServices.DebugOutChnl("PhysicalPath = " + request.PhysicalPath);
            //InternalRemotingServices.DebugOutChnl("QueryString = " + request.Url.QueryString); 
            InternalRemotingServices.DebugOutChnl("HttpMethod = " + request.HttpMethod);
            InternalRemotingServices.DebugOutChnl("ContentType = " + request.ContentType);
            InternalRemotingServices.DebugOutChnl("PathInfo = " + request.PathInfo);
 
            /*
            String[] keys = request.Headers.AllKeys; 
            String[] values = request.Headers.All; 

            for (int i=0; i
        public HttpRemotingHandler(Type type, Object srvID) 
        {
        } 
 
        //
        // Process the ASP+ Request 
        //
        public void ProcessRequest(HttpContext context)
        {
            InternalProcessRequest(context); 
        }
 
        // 
        // Internal
        // 
        // Transform the ASP+ Request and Response Structures in
        // Channel Structures:
        // ** Request.ServerVariables
        // ** Request.InputStream 
        // ** Response.Headers
        // 
        // This is needed to reduce the between dependency COR Channels 
        // and ASP+
        // 

        private void InternalProcessRequest(HttpContext context)
        {
            try 
            {
                HttpRequest httpRequest = context.Request; 
 
                // check if have previously loaded configuration
                if (!bLoadedConfiguration) 
                {
                    // locking a random static variable, so we can lock the class
                    lock(HttpRemotingHandler.ApplicationConfigurationFile)
                    { 
                        if (!bLoadedConfiguration)
                        { 
                            // Initialize IIS information 
                            IisHelper.Initialize();
 
                            // set application name
                            if (RemotingConfiguration.ApplicationName == null)
                                RemotingConfiguration.ApplicationName = httpRequest.ApplicationPath;
 
                            String filename = String.Concat(httpRequest.PhysicalApplicationPath,
                                                            ApplicationConfigurationFile); 
 
                            if (File.Exists(filename))
                            { 
                                try
                                {
                                    RemotingConfiguration.Configure(filename, false/*enableSecurity*/);
                                } 
                                catch (Exception e)
                                { 
                                    s_fatalException = e; 
                                    WriteException(context, e);
                                    return; 
                                }
                            }

                            try 
                            {
                                // do a search for a registered channel that wants to listen 
                                IChannelReceiverHook httpChannel = null; 
                                IChannel[] channels = ChannelServices.RegisteredChannels;
                                foreach (IChannel channel in channels) 
                                {
                                    IChannelReceiverHook hook = channel as IChannelReceiverHook;
                                    if (hook != null)
                                    { 
                                        if (String.Compare(hook.ChannelScheme, "http", StringComparison.OrdinalIgnoreCase) == 0)
                                        { 
                                            if (hook.WantsToListen) 
                                            {
                                                httpChannel = hook; 
                                                break;
                                            }
                                        }
                                    } 
                                }
 
                                if (httpChannel == null) 
                                {
                                    // No http channel that was listening found. 
                                    // Create a new channel.
                                    HttpChannel newHttpChannel = new HttpChannel();
                                    ChannelServices.RegisterChannel(newHttpChannel, false/*enableSecurity*/);
                                    httpChannel = newHttpChannel; 
                                }
 
                                String scheme = null; 
                                if (IisHelper.IsSslRequired)
                                    scheme = "https"; 
                                else
                                    scheme = "http";

                                String hookChannelUri = 
                                    scheme + "://" + CoreChannel.GetMachineIp();
 
                                int port = context.Request.Url.Port; 
                                String restOfUri = ":" + port + "/" + RemotingConfiguration.ApplicationName;
                                hookChannelUri += restOfUri; 

                                // add hook uri for this channel
                                httpChannel.AddHookChannelUri(hookChannelUri);
 
                                // If it uses ChannelDataStore, re-retrieve updated url in case it was updated.
                                ChannelDataStore cds = ((IChannelReceiver)httpChannel).ChannelData as ChannelDataStore; 
                                if (cds != null) 
                                    hookChannelUri = cds.ChannelUris[0];
 
                                IisHelper.ApplicationUrl = hookChannelUri;

                                // This is a hack to refresh the channel data.
                                //   In V-Next, we will add a ChannelServices.RefreshChannelData() api. 
                                ChannelServices.UnregisterChannel(null);
 
                                s_transportSink = new HttpHandlerTransportSink(httpChannel.ChannelSinkChain); 
                            }
                            catch (Exception e) 
                            {
                                s_fatalException = e;
                                WriteException(context, e);
                                return; 
                            }
                            bLoadedConfiguration = true; 
                        } 
                    }
                } 

                if (s_fatalException == null)
                {
                    if (!CanServiceRequest(context)) 
                        WriteException(context, new RemotingException(CoreChannel.GetResourceString("Remoting_ChnlSink_UriNotPublished")));
                    else 
                        s_transportSink.HandleRequest(context); 
                }
                else 
                    WriteException(context, s_fatalException);
            }
            catch (Exception e)
            { 
                WriteException(context, e);
            } 
        } // InternalProcessRequest 

        public bool IsReusable { get { return true; } } 

        string ComposeContentType(string contentType, Encoding encoding) {
            if (encoding != null) {
                StringBuilder sb = new StringBuilder(contentType); 
                sb.Append("; charset=");
                sb.Append(encoding.WebName); 
                return sb.ToString(); 
            }
            else 
                return contentType;
        }

        bool CanServiceRequest(HttpContext context) { 
            //Need to get the object uri first (cannot have query string)
            string requestUri = GetRequestUriForCurrentRequest(context); 
            string objectUri = HttpChannelHelper.GetObjectUriFromRequestUri(requestUri); 
            context.Items["__requestUri"] = requestUri;
 
            if (String.Compare(context.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase) != 0) {
                //If the request backed by an existing object
                if (RemotingServices.GetServerTypeForUri(requestUri) != null)
                    return true; 
            }
            else { 
                if (context.Request.QueryString.Count != 1) 
                    return false;
 
                string[] values =  context.Request.QueryString.GetValues(0);
                if (values.Length != 1 || String.Compare(values[0], "wsdl", StringComparison.OrdinalIgnoreCase) != 0)
                    return false;
 
                //If the request specifically asks for the wildcard
                if (String.Compare(objectUri, "RemoteApplicationMetadata.rem", StringComparison.OrdinalIgnoreCase) == 0) 
                    return true; 

                // find last index of ? 
                int index = requestUri.LastIndexOf('?');
                if (index != -1)
                    requestUri =  requestUri.Substring(0, index);
 
                //If the request backed by an existing object
                if (RemotingServices.GetServerTypeForUri(requestUri) != null) 
                    return true; 
            }
 
            //If the request is backed by an existing file on disk it should be serviced
            if (File.Exists(context.Request.PhysicalPath))
                return true;
 
            return false;
        } 
 
        string GetRequestUriForCurrentRequest(HttpContext context) {
            // we need to pull off any http specific data plus the application v-dir name 
            String rawUrl = context.Request.RawUrl;
            // here's where we pull off channel info
            String channelUri;
            String requestUri; 
            channelUri = HttpChannelHelper.ParseURL(rawUrl, out requestUri);
            if (channelUri == null) 
                requestUri = rawUrl; 

            // here's where we pull off the application v-dir name 
            String appName = RemotingConfiguration.ApplicationName;
            if (appName != null && appName.Length > 0 && requestUri.Length > appName.Length)
                //  "/appname" should always be in front, otherwise we wouldn't
                //   be in this handler. 
                requestUri = requestUri.Substring(appName.Length + 1);
 
            return requestUri; 
        }
 
        string GenerateFaultString(HttpContext context, Exception e) {
            //If the user has specified it's a development server (versus a production server) in ASP.NET config,
            //then we should just return e.ToString instead of extracting the list of messages.
            if (!CustomErrorsEnabled(context)) 
                return e.ToString();
            else { 
                return CoreChannel.GetResourceString("Remoting_InternalError"); 
            }
        } 

        void WriteException(HttpContext context, Exception e) {
            InternalRemotingServices.RemotingTrace("HttpHandler: Exception thrown...\n");
            InternalRemotingServices.RemotingTrace(e.StackTrace); 

            Stream outputStream = context.Response.OutputStream; 
            context.Response.Clear(); 
            context.Response.ClearHeaders();
            context.Response.ContentType = ComposeContentType("text/plain", Encoding.UTF8); 
            context.Response.StatusCode = (int) HttpStatusCode.InternalServerError;
            context.Response.StatusDescription = CoreChannel.GetResourceString("Remoting_InternalError");
            StreamWriter writer = new StreamWriter(outputStream, new UTF8Encoding(false));
            writer.WriteLine(GenerateFaultString(context, e)); 
            writer.Flush();
        } 
 
        internal static bool IsLocal(HttpContext context) {
            string localAddress = context.Request.ServerVariables["LOCAL_ADDR"]; 
            string remoteAddress = context.Request.UserHostAddress;
            return (context.Request.Url.IsLoopback || (localAddress != null && remoteAddress != null && localAddress == remoteAddress));
        }
 
        internal static bool CustomErrorsEnabled(HttpContext context) {
            try { 
                if (!context.IsCustomErrorEnabled) 
                    return false;
 
                return RemotingConfiguration.CustomErrorsEnabled(IsLocal(context));
            }
            catch {
                return true; 
            }
        } 
 
    } // HttpRemotingHandler
 
    public class HttpRemotingHandlerFactory : IHttpHandlerFactory
    {
        internal object _webServicesFactory = null;
        internal static Type s_webServicesFactoryType = null; 
        // REMACT: internal static Type s_remActType = null;
 
        internal static Object s_configLock = new Object(); 

        internal static Hashtable s_registeredDynamicTypeTable = Hashtable.Synchronized(new Hashtable()); 


        void DumpRequest(HttpContext context)
        { 
            HttpRequest request = context.Request;
            InternalRemotingServices.DebugOutChnl("Process Request called."); 
            InternalRemotingServices.DebugOutChnl("Path = " + request.Path); 
            InternalRemotingServices.DebugOutChnl("PhysicalPath = " + request.PhysicalPath);
            //InternalRemotingServices.DebugOutChnl("QueryString = " + request.Url.QueryString); 
            InternalRemotingServices.DebugOutChnl("HttpMethod = " + request.HttpMethod);
            InternalRemotingServices.DebugOutChnl("ContentType = " + request.ContentType);
            InternalRemotingServices.DebugOutChnl("PathInfo = " + request.PathInfo);
 
            /*
            String[] keys = request.Headers.AllKeys; 
            String[] values = request.Headers.All; 

            for (int i=0; i

                        

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