// --------------------------------------------------------------- Handlers
        /// <summary>
        /// Handles a CORS request of type
        /// <see cref="CORSRequestType"/>
        /// .SIMPLE.
        /// </summary>
        /// <param name="request">
        /// The
        /// <see cref="Javax.Servlet.Http.IHttpServletRequest"/>
        /// object.
        /// </param>
        /// <param name="response">
        /// The
        /// <see cref="Javax.Servlet.Http.IHttpServletResponse"/>
        /// object.
        /// </param>
        /// <param name="filterChain">
        /// The
        /// <see cref="Javax.Servlet.IFilterChain"/>
        /// object.
        /// </param>
        /// <exception cref="System.IO.IOException"/>
        /// <exception cref="Javax.Servlet.ServletException"/>
        /// <seealso><a href="http://www.w3.org/TR/cors/#resource-requests">Simple
        /// *      Cross-Origin Request, Actual Request, and Redirects</a></seealso>
        public void HandleSimpleCORS(IHttpServletRequest request, IHttpServletResponse response, IFilterChain filterChain)
        {
            CORSFilter.CORSRequestType requestType = CheckRequestType(request);
            if (!(requestType == CORSFilter.CORSRequestType.Simple || requestType == CORSFilter.CORSRequestType.Actual))
            {
                string message = "Expects a HttpServletRequest object of type " + CORSFilter.CORSRequestType.Simple + " or " + CORSFilter.CORSRequestType.Actual;
                throw new ArgumentException(message);
            }
            string origin = request.GetHeader(Edu.Stanford.Nlp.Naturalli.Demo.CORSFilter.RequestHeaderOrigin);
            string method = request.GetMethod();

            // Section 6.1.2
            if (!IsOriginAllowed(origin))
            {
                HandleInvalidCORS(request, response, filterChain);
                return;
            }
            if (!allowedHttpMethods.Contains(method))
            {
                HandleInvalidCORS(request, response, filterChain);
                return;
            }
            // Section 6.1.3
            // Add a single Access-Control-Allow-Origin header.
            if (anyOriginAllowed && !supportsCredentials)
            {
                // If resource doesn't support credentials and if any origin is
                // allowed
                // to make CORS request, return header with '*'.
                response.AddHeader(Edu.Stanford.Nlp.Naturalli.Demo.CORSFilter.ResponseHeaderAccessControlAllowOrigin, "*");
            }
            else
            {
                // If the resource supports credentials add a single
                // Access-Control-Allow-Origin header, with the value of the Origin
                // header as value.
                response.AddHeader(Edu.Stanford.Nlp.Naturalli.Demo.CORSFilter.ResponseHeaderAccessControlAllowOrigin, origin);
            }
            // Section 6.1.3
            // If the resource supports credentials, add a single
            // Access-Control-Allow-Credentials header with the case-sensitive
            // string "true" as value.
            if (supportsCredentials)
            {
                response.AddHeader(Edu.Stanford.Nlp.Naturalli.Demo.CORSFilter.ResponseHeaderAccessControlAllowCredentials, "true");
            }
            // Section 6.1.4
            // If the list of exposed headers is not empty add one or more
            // Access-Control-Expose-Headers headers, with as values the header
            // field names given in the list of exposed headers.
            if ((exposedHeaders != null) && (exposedHeaders.Count > 0))
            {
                string exposedHeadersString = Join(exposedHeaders, ",");
                response.AddHeader(Edu.Stanford.Nlp.Naturalli.Demo.CORSFilter.ResponseHeaderAccessControlExposeHeaders, exposedHeadersString);
            }
            // Forward the request down the filter chain.
            filterChain.DoFilter(request, response);
        }
        /// <summary>Handles a CORS request that violates specification.</summary>
        /// <param name="request">
        /// The
        /// <see cref="Javax.Servlet.Http.IHttpServletRequest"/>
        /// object.
        /// </param>
        /// <param name="response">
        /// The
        /// <see cref="Javax.Servlet.Http.IHttpServletResponse"/>
        /// object.
        /// </param>
        /// <param name="filterChain">
        /// The
        /// <see cref="Javax.Servlet.IFilterChain"/>
        /// object.
        /// </param>
        /// <exception cref="System.IO.IOException"/>
        /// <exception cref="Javax.Servlet.ServletException"/>
        public void HandleInvalidCORS(IHttpServletRequest request, IHttpServletResponse response, IFilterChain filterChain)
        {
            string origin = request.GetHeader(Edu.Stanford.Nlp.Naturalli.Demo.CORSFilter.RequestHeaderOrigin);
            string method = request.GetMethod();
            string accessControlRequestHeaders = request.GetHeader(RequestHeaderAccessControlRequestHeaders);
            string message = "Invalid CORS request; Origin=" + origin + ";Method=" + method;

            if (accessControlRequestHeaders != null)
            {
                message = message + ";Access-Control-Request-Headers=" + accessControlRequestHeaders;
            }
            response.SetContentType("text/plain");
            response.SetStatus(HttpServletResponseConstants.ScForbidden);
            response.ResetBuffer();
            Log(message);
        }
        /// <summary>Determines the request type.</summary>
        /// <param name="request"/>
        /// <returns/>
        public CORSFilter.CORSRequestType CheckRequestType(IHttpServletRequest request)
        {
            CORSFilter.CORSRequestType requestType = CORSFilter.CORSRequestType.InvalidCors;
            if (request == null)
            {
                throw new ArgumentException("HttpServletRequest object is null");
            }
            string originHeader = request.GetHeader(RequestHeaderOrigin);

            // Section 6.1.1 and Section 6.2.1
            if (originHeader != null)
            {
                if (originHeader.IsEmpty())
                {
                    requestType = CORSFilter.CORSRequestType.InvalidCors;
                }
                else
                {
                    if (!IsValidOrigin(originHeader))
                    {
                        requestType = CORSFilter.CORSRequestType.InvalidCors;
                    }
                    else
                    {
                        string method = request.GetMethod();
                        if (method != null && HttpMethods.Contains(method))
                        {
                            if ("OPTIONS".Equals(method))
                            {
                                string accessControlRequestMethodHeader = request.GetHeader(RequestHeaderAccessControlRequestMethod);
                                if (accessControlRequestMethodHeader != null && !accessControlRequestMethodHeader.IsEmpty())
                                {
                                    requestType = CORSFilter.CORSRequestType.PreFlight;
                                }
                                else
                                {
                                    if (accessControlRequestMethodHeader != null && accessControlRequestMethodHeader.IsEmpty())
                                    {
                                        requestType = CORSFilter.CORSRequestType.InvalidCors;
                                    }
                                    else
                                    {
                                        requestType = CORSFilter.CORSRequestType.Actual;
                                    }
                                }
                            }
                            else
                            {
                                if ("GET".Equals(method) || "HEAD".Equals(method))
                                {
                                    requestType = CORSFilter.CORSRequestType.Simple;
                                }
                                else
                                {
                                    if ("POST".Equals(method))
                                    {
                                        string contentType = request.GetContentType();
                                        if (contentType != null)
                                        {
                                            contentType = contentType.ToLower().Trim();
                                            if (SimpleHttpRequestContentTypeValues.Contains(contentType))
                                            {
                                                requestType = CORSFilter.CORSRequestType.Simple;
                                            }
                                            else
                                            {
                                                requestType = CORSFilter.CORSRequestType.Actual;
                                            }
                                        }
                                    }
                                    else
                                    {
                                        if (ComplexHttpMethods.Contains(method))
                                        {
                                            requestType = CORSFilter.CORSRequestType.Actual;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            else
            {
                requestType = CORSFilter.CORSRequestType.NotCors;
            }
            return(requestType);
        }