Cross-origin resource sharing is fundamental that can make visible the resources which are hidden. Cross-Origin Resource Sharing (CORS) is a specification that enables truly open access across domain boundaries. CORS allows web scripts to interact more openly with content outside of the original domain, leading to better integration between web services. Cross-origin resource sharing allows blocked resources just like – fonts, on a web page to be requested from another domain outside the domain from which the resource originated.
CORS defines a way in which a browser and server can interact to determine whether or not it is safe to allow the cross-origin request. It allows for more freedom and functionality than purely same-origin requests but is more secure than simply allowing all cross-origin requests.
JavaScript and the web programming has grown by leaps and bounds over the years, but the same-origin policy still remains. This prevents JavaScript from making requests across domain boundaries and has spawned various hacks for making cross-domain requests.
CORS introduces a standard mechanism that can be used by all browsers for implementing cross-domain requests. The spec defines a set of headers that allow the browser and server to communicate about which requests are (and are not) allowed. CORS continues the spirit of the open web by bringing API access to all.
To add the CORS authorization to the header using Apache, simply add the following line inside either the <Directory>
,<Location>
<Files>
or <VirtualHost>
sections of your server config (usually located in a *.conf files, such as httpd.conf or apache.conf), or within a .htaccess
file:
Header set Access-Control-Allow-Origin "*"
To ensure that your changes are correct, it is strongly recommended that you use
apachectl -t
to check your configuration changes for errors. After this passes, you may need to reload Apache to make sure your changes are applied by running the command
sudo service apache2 reload
or
apachectl -k graceful
Altering headers requires the use of mod_headers. Mod_headers is enabled by default in Apache, however, you may want to ensure it’s enabled by run
a2enmod headers
Note: you can also use add
rather than set
, but be aware that add
can add the header multiple times, so it’s likely safer to use set.
For Python-based applications in Google App Engine, the self.response.headers.add_header()
method can be used, such as:
class CORSEnabledHandler(webapp.RequestHandler): def get(self): self.response.headers.add_header("Access-Control-Allow-Origin", "*") self.response.headers['Content-Type'] = 'text/csv' self.response.out.write(self.dump_csv())
For Java-based applications, use resp.addHeader()
:
public void doGet(HttpServletRequest req, HttpServletResponse resp) { resp.addHeader("Access-Control-Allow-Origin", "*"); resp.addHeader("Content-Type", "text/csv"); resp.getWriter().append(csvString); }
And for Go-based applications, use w.Header().Add()
:
func doGet(w http.ResponseWriter, r *http.Request) { w.Header().Add("Access-Control-Allow-Origin", "*") w.Header().Add("Content-Type", "text/csv") fmt.Fprintf(w, csvData) }
If you don’t have access to configure IIS, you can still add the header through ASP.NET by adding the following line to your source pages:
Response.AppendHeader("Access-Control-Allow-Origin", "*");
ASP.NET Web API 2 supports CORS.
To enable CORS support, add the Microsoft.AspNet.WebApi.Cors NuGet packages to your project.
Add this code to your configuration:
public static void Register(HttpConfiguration config) { // New code config.EnableCors(); }
To enable cross-origin requests, add the [EnableCors] attribute to your Web API controller or controller method:
[EnableCors(origins: "http://example.com", headers: "*", methods: "*")] public class TestController : ApiController { // Controller methods not shown... }
The method described above can also be used to enable CORS across the API without annotating each controller:
public static void Register(HttpConfiguration config) { var corsAttr = new EnableCorsAttribute("http://example.com", "*", "*"); config.EnableCors(corsAttr); }
Amazon API Gateway adds support for CORS enabling through a simple button in the API Gateway console. Unfortunately, that button has a partial behavior, thus setting CORS correctly only for 200 answers (so not other HTTP status codes) and ignoring Jquery header support. The best solution considered so far is about avoiding to use the CORS button and set configurations manually.
1. Log into API Gateway console
2. Create all the REST resources that need to be exposed with their methods before setting up CORS (if new resources/methods are created after enabling CORS, these steps must be repeated)
3. Select a resource
4. Add OPTIONS method, choose as integration type “mock”
5. For each Method of a resource
6. Go to Response Method
7. Add all the response method that should be supported (i.e. 200, 500, etc.)
8. For each response code set Response Headers to
X-Requested-With
Access-Control-Allow-Headers
Access-Control-Allow-Origin
Access-Control-Allow-Methods
9. Go to Integration Response, select one of the created response codes, then Header Mappings
10. Insert default values for headers
example:
X-Requested-With: ‘*’
Access-Control-Allow-Headers: ‘Content-Type,X-Amz-Date,Authorization,X-API-Key,x-requested-with’
Access-Control-Allow-Origin: ‘*’
Access-Control-Allow-Methods: ‘POST,GET,OPTIONS’
This operation has to be repeated for each method, including the newly created OPTIONS
11. Deploy the API to a stage
12. Check using http://client.cors-api.appspot.com/client that CORS requests have been successfully enabled
To add the CORS authorization to the header using Caddy, simply add the following line inside your caddyfile:
cors
This will allow all resources to be accessed from every domain.
You can also be more specific, i.e. allow specific resources to specific domains:
cors /foo http://mysite.com http://anothertrustedsite.com
There are many more options you can use, here is a full example, as shown in the caddyserver docs:
cors / { origin http://allowedSite.com origin http://anotherSite.org https://anotherSite.org methods POST,PUT allow_credentials false max_age 3600 allowed_headers X-Custom-Header,X-Foobar exposed_headers X-Something-Special,SomethingElse }
Just output the line:
Access-Control-Allow-Origin: *
.. as part of your CGI script’s headers, for example, in Perl (using CGI.pm):
print header( -type => 'text/turtle', -content_location => 'mydata.ttl', -access_control_allow_origin => '*', );
The module Plack::Middleware::CrossOrigin provides a complete CORS server side implementation. To allow any request from any location, just add this to your builder:
enable 'CrossOrigin', origins => '*';
print "Content-Type: text/turtle" print "Content-Location: mydata.ttl" print "Access-Control-Allow-Origin: *"
In your ExpressJS app on node.js, do the following with your routes:
app.use(function(req, res, next) { res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); next(); }); app.get('/', function(req, res, next) { // Handle the get for this route }); app.post('/', function(req, res, next) { // Handle the post for this route });
To CORS-enable Microsoft IIS6, perform the following steps:
Access-Control-Allow-Origin
as the header name*
as the header valueFor Microsoft IIS7, merge this into the web.config
file at the root of your application or site:
<?xml version="1.0" encoding="utf-8"?> <configuration> <system.webServer> <httpProtocol> <customHeaders> <add name="Access-Control-Allow-Origin" value="*" /> </customHeaders> </httpProtocol> </system.webServer> </configuration>
If you don’t have a web.config
file already, or don’t know what one is, just create a new file called web.config
containing the snippet above.
To add CORS authorization to a Meteor application, use the webapp package’s WebApp.connectHandlers
to customize HTTP headers.
// Listen to incoming HTTP requests, can only be used on the server WebApp.rawConnectHandlers.use(function(req, res, next) { res.setHeader("Access-Control-Allow-Origin", "*"); return next(); });
Use the optional path
argument to only call the handler for paths that match a specified string.
// Listen to incoming HTTP requests, can only be used on the server WebApp.rawConnectHandlers.use("/public", function(req, res, next) { res.setHeader("Access-Control-Allow-Origin", "*"); return next(); });
The following Nginx configuration enables CORS, with support for preflight requests.
# # Wide-open CORS config for nginx # location / { if ($request_method = 'OPTIONS') { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; # # Custom headers and headers various browsers *should* be OK with but aren't # add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type'; # # Tell client that this pre-flight info is valid for 20 days # add_header 'Access-Control-Max-Age' 1728000; add_header 'Content-Type' 'text/plain charset=UTF-8'; add_header 'Content-Length' 0; return 204; } if ($request_method = 'POST') { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type'; } if ($request_method = 'GET') { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type'; } }
The module Plack::Middleware::CrossOrigin provides a complete CORS server side implementation. To allow any request from any location, just add this to your builder:
enable 'CrossOrigin', origins => '*';
This module is also available in Debian and Ubuntu as libplack-middleware-crossorigin-perl.
If you don’t have access to configure Apache, you can still send the header from a PHP script. It’s a case of adding the following to your PHP scripts:
<?php header("Access-Control-Allow-Origin: *");
Note: as with all uses of the PHP header function, this must be before any output has been sent from the server.
If you don’t have access to configure you web server, you can still send the header from a Coldfusion script. It’s a case of adding the following to your Coldfusion scripts:
<cfheader name="Access-Control-Allow-Origin" value="*">
var response = getPageContext().getResponse(); response.setHeader("Access-Control-Allow-Origin","*");
Note: This needs to be set before any output has been sent from the server.
Apache Tomcat includes support for CORS (Starting from Tomcat version 7.0.41).
Here is an example from those docs that demonstrates a minimal CORS configuration:
<filter> <filter-name>CorsFilter</filter-name> <filter-class>org.apache.catalina.filters.CorsFilter</filter-class> </filter> <filter-mapping> <filter-name>CorsFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
These instance/server-level settings require OpenLink Virtuoso Open Source (VOS) 6.1.3 or later.
*
or an origin, such as orhttp://example.com:8080
http://foo.example.com
. Scripts are authorized to retrieve a resource if that resource either uses the wildcard or lists the origin of the script. For this example, enter the following single URI: http://demo.openlinksw.com
For older versions of Virtuoso, any of the Web Application-level instructions below may be used. Any Virtuoso-based application can implement CORS checking through well-known HTTP functions http_request_header() and http_header(), for example:
<?vsp IF (http_request_header (lines, 'Origin', NULL) = 'http://host.org') { http_header ('Access-Control-Allow-Origin: http://host.org\r\n'); } ELSE { RETURN; } -- Additional code here --- ?>
For WCF service you have to develop new behavior and include it in the endpoint configuration:
public class CustomHeaderMessageInspector : IDispatchMessageInspector { Dictionary<string, string> requiredHeaders; public CustomHeaderMessageInspector (Dictionary<string, string> headers) { requiredHeaders = headers ?? new Dictionary<string, string>(); } public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext) { return null; } public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState) { var httpHeader = reply.Properties["httpResponse"] as HttpResponseMessageProperty; foreach (var item in requiredHeaders) { httpHeader.Headers.Add(item.Key, item.Value); } } }
Create Endpoint Behavior and use Message Inspector to add headers
public class EnableCrossOriginResourceSharingBehavior : BehaviorExtensionElement, IEndpointBehavior { public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters) { } public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime) { } public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher) { var requiredHeaders = new Dictionary<string, string>(); requiredHeaders.Add("Access-Control-Allow-Origin", "*"); requiredHeaders.Add("Access-Control-Request-Method", "POST,GET,PUT,DELETE,OPTIONS"); requiredHeaders.Add("Access-Control-Allow-Headers", "X-Requested-With,Content-Type"); endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new CustomHeaderMessageInspector(requiredHeaders)); } public void Validate(ServiceEndpoint endpoint) { } public override Type BehaviorType { get { return typeof(EnableCrossOriginResourceSharingBehavior); } } protected override object CreateBehavior() { return new EnableCrossOriginResourceSharingBehavior(); } }
Register new behavior in web.config
<extensions> <behaviorExtensions> <add name="crossOriginResourceSharingBehavior" type="Services.Behaviours.EnableCrossOriginResourceSharingBehavior, Services, Version=1.0.0.0, Culture=neutral" /> </behaviorExtensions> </extensions>
Add new behavior to endpoint behavior configuration
<endpointBehaviors> <behavior name="jsonBehavior"> <webHttp /> <crossOriginResourceSharingBehavior /> </behavior> </endpointBehaviors>
Configure endpoint
<endpoint address="api" binding="webHttpBinding" behaviorConfiguration="jsonBehavior" contract="Service.IServiceContract" />
Thanks for reading this post. Hoping this tutorial will help you to Enable Cross-Origin Resource Sharing.
Please give your comments and remark below.
Leave a Reply