/// <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> /// Called by the server (via the Service method) /// to allow a servlet to handle a TRACE request. /// /// A TRACE returns the headers sent with the TRACE /// request to the client, so that they can be used in /// debugging. There's no need to override this method. /// </summary> /// <param name="req"> /// the IHttpServletRequest object that /// contains the request the client made of /// the servlet /// </param> /// <param name="resp"> /// the IHttpServletResponse object that /// contains the response the servlet returns /// to the client /// </param> /// <exception cref="IOException"> /// if an input or output error occurs /// while the servlet is handling the /// TRACE request /// </exception> /// <exception cref="ServletException"> /// if the request for the /// TRACE cannot be handled /// </exception> protected void DoTrace(IHttpServletRequest req, IHttpServletResponse resp) { int responseLength; string CRLF = "\r\n"; string responseString = "TRACE " + req.RequestURI + " " + req.Protocol; foreach (object elem in req.HeaderNames) { string headerName = (string)elem; responseString += CRLF + headerName + ": " + req.GetHeader(headerName); } responseString += CRLF; responseLength = responseString.Length; resp.ContentType = "message/http"; resp.ContentLength = responseLength; ServletOutputStream output = resp.OutputStream; output.Print(responseString); output.Close(); return; }
// --------------------------------------------------------------- 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); }
// NOOP // -------------------------------------------------------- Utility methods /// <summary> /// Decorates the /// <see cref="Javax.Servlet.Http.IHttpServletRequest"/> /// , with CORS attributes. /// <ul> /// <li><b>cors.isCorsRequest:</b> Flag to determine if request is a CORS /// request. Set to <code>true</code> if CORS request; <code>false</code> /// otherwise.</li> /// <li><b>cors.request.origin:</b> The Origin URL.</li> /// <li><b>cors.request.type:</b> Type of request. Values: /// <code>simple</code> or <code>preflight</code> or <code>not_cors</code> or /// <code>invalid_cors</code></li> /// <li><b>cors.request.headers:</b> Request headers sent as /// 'Access-Control-Request-Headers' header, for pre-flight request.</li> /// </ul> /// </summary> /// <param name="request"> /// The /// <see cref="Javax.Servlet.Http.IHttpServletRequest"/> /// object. /// </param> /// <param name="corsRequestType"> /// The /// <see cref="CORSRequestType"/> /// object. /// </param> public static void DecorateCORSProperties(IHttpServletRequest request, CORSFilter.CORSRequestType corsRequestType) { if (request == null) { throw new ArgumentException("HttpServletRequest object is null"); } if (corsRequestType == null) { throw new ArgumentException("CORSRequestType object is null"); } switch (corsRequestType) { case CORSFilter.CORSRequestType.Simple: { request.SetAttribute(Edu.Stanford.Nlp.Naturalli.Demo.CORSFilter.HttpRequestAttributeIsCorsRequest, true); request.SetAttribute(Edu.Stanford.Nlp.Naturalli.Demo.CORSFilter.HttpRequestAttributeOrigin, request.GetHeader(Edu.Stanford.Nlp.Naturalli.Demo.CORSFilter.RequestHeaderOrigin)); request.SetAttribute(Edu.Stanford.Nlp.Naturalli.Demo.CORSFilter.HttpRequestAttributeRequestType, corsRequestType.ToString().ToLower()); break; } case CORSFilter.CORSRequestType.Actual: { request.SetAttribute(Edu.Stanford.Nlp.Naturalli.Demo.CORSFilter.HttpRequestAttributeIsCorsRequest, true); request.SetAttribute(Edu.Stanford.Nlp.Naturalli.Demo.CORSFilter.HttpRequestAttributeOrigin, request.GetHeader(Edu.Stanford.Nlp.Naturalli.Demo.CORSFilter.RequestHeaderOrigin)); request.SetAttribute(Edu.Stanford.Nlp.Naturalli.Demo.CORSFilter.HttpRequestAttributeRequestType, corsRequestType.ToString().ToLower()); break; } case CORSFilter.CORSRequestType.PreFlight: { request.SetAttribute(Edu.Stanford.Nlp.Naturalli.Demo.CORSFilter.HttpRequestAttributeIsCorsRequest, true); request.SetAttribute(Edu.Stanford.Nlp.Naturalli.Demo.CORSFilter.HttpRequestAttributeOrigin, request.GetHeader(Edu.Stanford.Nlp.Naturalli.Demo.CORSFilter.RequestHeaderOrigin)); request.SetAttribute(Edu.Stanford.Nlp.Naturalli.Demo.CORSFilter.HttpRequestAttributeRequestType, corsRequestType.ToString().ToLower()); string headers = request.GetHeader(RequestHeaderAccessControlRequestHeaders); if (headers == null) { headers = string.Empty; } request.SetAttribute(Edu.Stanford.Nlp.Naturalli.Demo.CORSFilter.HttpRequestAttributeRequestHeaders, headers); break; } case CORSFilter.CORSRequestType.NotCors: { request.SetAttribute(Edu.Stanford.Nlp.Naturalli.Demo.CORSFilter.HttpRequestAttributeIsCorsRequest, false); break; } default: { // Don't set any attributes break; } } }
/// <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); }
/// <summary>Handles CORS pre-flight request.</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 HandlePreflightCORS(IHttpServletRequest request, IHttpServletResponse response, IFilterChain filterChain) { CORSFilter.CORSRequestType requestType = CheckRequestType(request); if (requestType != CORSFilter.CORSRequestType.PreFlight) { throw new ArgumentException("Expects a HttpServletRequest object of type " + CORSFilter.CORSRequestType.PreFlight.ToString().ToLower()); } string origin = request.GetHeader(Edu.Stanford.Nlp.Naturalli.Demo.CORSFilter.RequestHeaderOrigin); // Section 6.2.2 if (!IsOriginAllowed(origin)) { HandleInvalidCORS(request, response, filterChain); return; } // Section 6.2.3 string accessControlRequestMethod = request.GetHeader(Edu.Stanford.Nlp.Naturalli.Demo.CORSFilter.RequestHeaderAccessControlRequestMethod); if (accessControlRequestMethod == null || (!HttpMethods.Contains(accessControlRequestMethod.Trim()))) { HandleInvalidCORS(request, response, filterChain); return; } else { accessControlRequestMethod = accessControlRequestMethod.Trim(); } // Section 6.2.4 string accessControlRequestHeadersHeader = request.GetHeader(Edu.Stanford.Nlp.Naturalli.Demo.CORSFilter.RequestHeaderAccessControlRequestHeaders); IList <string> accessControlRequestHeaders = new LinkedList <string>(); if (accessControlRequestHeadersHeader != null && !accessControlRequestHeadersHeader.Trim().IsEmpty()) { string[] headers = accessControlRequestHeadersHeader.Trim().Split(","); foreach (string header in headers) { accessControlRequestHeaders.Add(header.Trim().ToLower()); } } // Section 6.2.5 if (!allowedHttpMethods.Contains(accessControlRequestMethod)) { HandleInvalidCORS(request, response, filterChain); return; } // Section 6.2.6 if (!accessControlRequestHeaders.IsEmpty()) { foreach (string header in accessControlRequestHeaders) { if (!allowedHttpHeaders.Contains(header)) { HandleInvalidCORS(request, response, filterChain); return; } } } // Section 6.2.7 if (supportsCredentials) { response.AddHeader(Edu.Stanford.Nlp.Naturalli.Demo.CORSFilter.ResponseHeaderAccessControlAllowOrigin, origin); response.AddHeader(Edu.Stanford.Nlp.Naturalli.Demo.CORSFilter.ResponseHeaderAccessControlAllowCredentials, "true"); } else { if (anyOriginAllowed) { response.AddHeader(Edu.Stanford.Nlp.Naturalli.Demo.CORSFilter.ResponseHeaderAccessControlAllowOrigin, "*"); } else { response.AddHeader(Edu.Stanford.Nlp.Naturalli.Demo.CORSFilter.ResponseHeaderAccessControlAllowOrigin, origin); } } // Section 6.2.8 if (preflightMaxAge > 0) { response.AddHeader(Edu.Stanford.Nlp.Naturalli.Demo.CORSFilter.ResponseHeaderAccessControlMaxAge, preflightMaxAge.ToString()); } // Section 6.2.9 response.AddHeader(Edu.Stanford.Nlp.Naturalli.Demo.CORSFilter.ResponseHeaderAccessControlAllowMethods, accessControlRequestMethod); // Section 6.2.10 if ((allowedHttpHeaders != null) && (!allowedHttpHeaders.IsEmpty())) { response.AddHeader(Edu.Stanford.Nlp.Naturalli.Demo.CORSFilter.ResponseHeaderAccessControlAllowHeaders, Join(allowedHttpHeaders, ",")); } }