public void Register(IAppHost appHost) { if (appHost.HasMultiplePlugins<CorsFeature>()) throw new NotSupportedException("CorsFeature has already been registered"); if (!string.IsNullOrEmpty(allowedOrigins) && allowOriginWhitelist == null) appHost.Config.GlobalResponseHeaders.Add(HttpHeaders.AllowOrigin, allowedOrigins); if (!string.IsNullOrEmpty(allowedMethods)) appHost.Config.GlobalResponseHeaders.Add(HttpHeaders.AllowMethods, allowedMethods); if (!string.IsNullOrEmpty(allowedHeaders)) appHost.Config.GlobalResponseHeaders.Add(HttpHeaders.AllowHeaders, allowedHeaders); if (allowCredentials) appHost.Config.GlobalResponseHeaders.Add(HttpHeaders.AllowCredentials, "true"); Action<IRequest, IResponse> allowOriginFilter = null; if (allowOriginWhitelist != null) { allowOriginFilter = (httpReq, httpRes) => { var origin = httpReq.Headers.Get("Origin"); if (allowOriginWhitelist.Contains(origin)) { httpRes.AddHeader(HttpHeaders.AllowOrigin, origin); } }; appHost.PreRequestFilters.Add(allowOriginFilter); } if (AutoHandleOptionsRequests) { //Handles Request and closes Response after emitting global HTTP Headers var emitGlobalHeadersHandler = new CustomActionHandler( (httpReq, httpRes) => { if (allowOriginFilter != null) allowOriginFilter(httpReq, httpRes); httpRes.EndRequest(); }); appHost.RawHttpHandlers.Add(httpReq => httpReq.HttpMethod == HttpMethods.Options ? emitGlobalHeadersHandler : null); } }
public void Register(IAppHost appHost) { if (isInstalled) return; isInstalled = true; Action<IRequest, IResponse> allowOriginFilter = (httpReq, httpRes) => { // Following the flow chart given at http://www.html5rocks.com/static/images/cors_server_flowchart.png var origin = httpReq.Headers.Get(MoreHttpHeaders.Origin); if (origin == null) // Not a valid CORS request return; var methods = httpReq.Headers.Get(MoreHttpHeaders.RequestMethod); bool preflight; if (methods != null && httpReq.Verb == "OPTIONS") { preflight = true; var requestMethod = httpReq.Headers.Get(MoreHttpHeaders.RequestMethod); if (requestMethod == null) { // Not a valid preflight request return; } var requestHeader = httpReq.Headers.Get(MoreHttpHeaders.RequestHeader); if (requestHeader != null && !allowHeaders.Contains(requestHeader)) { // Not a valid preflight request return; } httpRes.AddHeader(HttpHeaders.AllowMethods, allowMethods); httpRes.AddHeader(HttpHeaders.AllowHeaders, allowHeaders); if (maxAgeSeconds.HasValue) httpRes.AddHeader(MoreHttpHeaders.MaxAge, maxAgeSeconds.Value.ToString()); } else { preflight = false; // Actual request, should response headers be exposed to the client? if (exposeHeaders) httpRes.AddHeader(MoreHttpHeaders.ExposeHeaders, allowHeaders); } if (this.allowOrigins == null) { httpRes.AddHeader(HttpHeaders.AllowOrigin, "*"); } else if (allowOrigins.Contains(origin)) { httpRes.AddHeader(HttpHeaders.AllowOrigin, origin); // See http://www.w3.org/TR/cors/#resource-implementation httpRes.AddHeader(MoreHttpHeaders.Vary, MoreHttpHeaders.Origin); } if (allowCredentials) { httpRes.AddHeader(HttpHeaders.AllowCredentials, allowCredentials.ToString().ToLower()); } if (preflight) { httpRes.AddHeader(HttpHeaders.ContentType, "text/html; charset=utf-8"); httpRes.StatusCode = (int)HttpStatusCode.OK; httpRes.Close(); } }; appHost.PreRequestFilters.Add(allowOriginFilter); if (autoHandleOptionsRequests) { CustomActionHandler handler = new CustomActionHandler((httpReq, httpRes) => { if (allowOriginFilter != null) { allowOriginFilter.Invoke(httpReq, httpRes); } httpRes.EndRequest(); }); appHost.RawHttpHandlers.Add((httpReq) => { if (httpReq.Verb != "OPTIONS") return null; return handler; }); } }