开发者

Support OPTIONS request header in aspx page

开发者 https://www.devze.com 2023-03-17 06:31 出处:网络
I\'m maintaining a service that accepts a form post and in adding support for CORS requests I\'ve come across the issue in Firefox 3.6 where it sends a preflight request with an OPTIONS request header

I'm maintaining a service that accepts a form post and in adding support for CORS requests I've come across the issue in Firefox 3.6 where it sends a preflight request with an OPTIONS request header.

I didn't have any trouble adding the necessary Access-Control-Allow-Origin response headers with a generic http handler page, but I'm having difficulty with the full 开发者_StackOverflowblown aspx page. It's definitely not hitting Page_Load and I can't figure out where in the page lifecycle it's getting stuck.

Anyone have any ideas?

Thanks!


You can do this with an HttpModule and an HttpHandler

I think some of this came from an article somewhere, and other parts of it were developed in house... so if some of it came from somewhere else, I apologize in advance for not giving the due credit:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace YourNamespaceHere
{
    using System;
    using System.Web; 
    using System.Collections;

    public class CrossOriginModule : IHttpModule {
        public String ModuleName {
            get { return "CrossOriginModule"; } 
        }    

        public void Init(HttpApplication application) {
            application.BeginRequest += (new EventHandler(this.Application_BeginRequest));
        }

        private void Application_BeginRequest(Object source, EventArgs e) {
            HttpApplication application = (HttpApplication)source;
            HttpContext context = application.Context;
            CrossOriginHandler.SetAllowCrossSiteRequestOrigin(context);
        }

        public void Dispose() 
        {
        }
    }

   public class CrossOriginHandler : IHttpHandler
    {
        #region IHttpHandler Members
        public bool IsReusable
        {
            get { return true; }
        }

        public void ProcessRequest(HttpContext context)
        {
            //Clear the response (just in case)
            ClearResponse(context);

            //Checking the method
            switch (context.Request.HttpMethod.ToUpper())
            {
                //Cross-Origin preflight request
                case "OPTIONS":
                    //Set allowed method and headers
                    SetAllowCrossSiteRequestHeaders(context);
                    //Set allowed origin
                    //This happens for us with our module:
                    SetAllowCrossSiteRequestOrigin(context);
                    //End
                    context.Response.End();
                    break;

                default:
                    context.Response.Headers.Add("Allow", "OPTIONS");
                    context.Response.StatusCode = 405;
                    break;
            }

            context.ApplicationInstance.CompleteRequest();
        }
        #endregion

        #region Methods
        protected void ClearResponse(HttpContext context)
        {
            context.Response.ClearHeaders();
            context.Response.ClearContent();
            context.Response.Clear();
        }

        protected void SetNoCacheHeaders(HttpContext context)
        {
            context.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
            context.Response.Cache.SetValidUntilExpires(false);
            context.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
            context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
            context.Response.Cache.SetNoStore();
        }
        #endregion

        public static void SetAllowCrossSiteRequestHeaders(HttpContext context)
        {
            string requestMethod = context.Request.Headers["Access-Control-Request-Method"];

            context.Response.AppendHeader("Access-Control-Allow-Methods", "GET,POST");

            //We allow any custom headers
            string requestHeaders = context.Request.Headers["Access-Control-Request-Headers"];
            if (!String.IsNullOrEmpty(requestHeaders))
                context.Response.AppendHeader("Access-Control-Allow-Headers", requestHeaders);
        }

        public static void SetAllowCrossSiteRequestOrigin(HttpContext context)
        {
            string origin = context.Request.Headers["Origin"];
            if (!String.IsNullOrEmpty(origin))
                context.Response.AppendHeader("Access-Control-Allow-Origin", origin);
            else
                //This is necessary for Chrome/Safari actual request
                context.Response.AppendHeader("Access-Control-Allow-Origin", "*");
        }
    }
}

And in the Web.config:

  ...
  <system.webServer>
     ...
     <modules runAllManagedModulesForAllRequests="true">
     ...
           <add name="CrossOriginModule" preCondition="managedHandler" type="YOURNANMESPACEHERE.CrossOriginModule, ASSEMBLYNAME" />
    </modules>
    <handlers>
           <add name="CrossOrigin" verb="OPTIONS" path="*" type="YOURNAMESPACEHERE.CrossOriginHandler, ASSEMBLYNAME" />
    </handlers>
  </system.webServer>


Steve's answer is amazing, it inevitably lead me to a resolution in my case, which is why I up-voted it. However, it seems to me that an HttpHandler may not be explicitly necessary. So I configured CORS, strictly in the module itself which jacks into the request pipeline. My code:

using System;
using System.Web;

namespace NAMESPACE.HttpModules
{
    public class CrossOriginModule : IHttpModule
    {
        public String ModuleName
        {
            get { return "CrossOriginModule"; }
        }

        public void Init(HttpApplication application)
        {
            application.BeginRequest += (new EventHandler(this.Application_BeginRequest));
        }

        private void Application_BeginRequest(Object source, EventArgs e)
        {
            HttpApplication application = (HttpApplication)source;
            HttpContext context = application.Context;

            string httpMethod = context.Request.HttpMethod.ToUpper();

            //preflight
            if (httpMethod == "OPTIONS")
            {
                ClearResponse(context);

                //Set allowed method and headers
                SetAllowCrossSiteRequestHeaders(context);
                //Set allowed origin
                SetAllowCrossSiteRequestOrigin(context);

                //end request
                context.ApplicationInstance.CompleteRequest();
            }
            else
            {
                SetAllowCrossSiteRequestOrigin(context);
            }

        }
        static void SetAllowCrossSiteRequestHeaders(HttpContext context)
        {
            string requestMethod = context.Request.Headers["Access-Control-Request-Method"];

            context.Response.AppendHeader("Access-Control-Allow-Methods", "GET,POST");

            //We allow any custom headers
            string requestHeaders = context.Request.Headers["Access-Control-Request-Headers"];
            if (!String.IsNullOrEmpty(requestHeaders))
                context.Response.AppendHeader("Access-Control-Allow-Headers", requestHeaders);

            //allow credentials
            context.Response.AppendHeader("Access-Control-Allow-Credentials", "true");
        }

        static void SetAllowCrossSiteRequestOrigin(HttpContext context)
        {
            string origin = context.Request.Headers["Origin"];
            if (!String.IsNullOrEmpty(origin))
                context.Response.AppendHeader("Access-Control-Allow-Origin", origin);
            else
                context.Response.AppendHeader("Access-Control-Allow-Origin", "*");
        }

        static void ClearResponse(HttpContext context)
        {
            context.Response.ClearHeaders();
            context.Response.ClearContent();
            context.Response.Clear();
        }

        public void Dispose()
        {
        }
    }

}

And in your web.config

<modules runAllManagedModulesForAllRequests="true">
    <add name="CrossOriginModule" preCondition="managedHandler" type="NAMESPACE.HttpModules.CrossOriginModule" />
</modules>

This will configure the response headers as needed, and let MVC handle the request as it normally would.


make sure you have the following in your web.config, and follow my answer (it has almost no code) https://stackoverflow.com/a/62583142/2411916

<configuration>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>
</configuration>
0

精彩评论

暂无评论...
验证码 换一张
取 消